123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- <template>
- <div id="queue">
- <draggable
- tag="transition-group"
- :component-data="{
- name: !drag ? 'draggable-list-transition' : null
- }"
- :class="{
- 'actionable-button-hidden': !actionableButtonVisible,
- 'scrollable-list': true
- }"
- v-if="queue.length > 0"
- v-model="queue"
- item-key="_id"
- v-bind="dragOptions"
- @start="drag = true"
- @end="drag = false"
- @change="repositionSongInQueue"
- >
- <template #item="{element, index}">
- <song-item
- :song="element"
- :requested-by="
- station.type === 'community' &&
- station.partyMode === true
- "
- :class="{
- 'item-draggable': isAdminOnly() || isOwnerOnly()
- }"
- :disabled-actions="[]"
- >
- <template v-if="isAdminOnly() || isOwnerOnly()" #actions>
- <div class="song-actions">
- <confirm
- v-if="isOwnerOnly() || isAdminOnly()"
- placement="left"
- @confirm="removeFromQueue(element.youtubeId)"
- >
- <i
- class="material-icons delete-icon"
- content="Remove Song from Queue"
- v-tippy
- >delete_forever</i
- >
- </confirm>
- <i
- class="material-icons"
- v-if="index > 0"
- @click="moveSongToTop(element, index)"
- content="Move to top of Queue"
- v-tippy
- >vertical_align_top</i
- >
- <i
- v-if="queue.length - 1 !== index"
- @click="moveSongToBottom(element, index)"
- class="material-icons"
- content="Move to bottom of Queue"
- v-tippy
- >vertical_align_bottom</i
- >
- </div>
- </template>
- </song-item>
- </template>
- </draggable>
- <p class="nothing-here-text" v-else>
- There are no songs currently queued
- </p>
- <button
- class="button is-primary tab-actionable-button"
- v-if="
- sector === 'station' &&
- loggedIn &&
- station.type === 'community' &&
- station.partyMode &&
- ((station.locked && isOwnerOnly()) ||
- !station.locked ||
- (station.locked && isAdminOnly() && dismissedWarning))
- "
- @click="openModal('manageStation') & showManageStationTab('search')"
- >
- <i class="material-icons icon-with-button">queue</i>
- <span class="optional-desktop-only-text"> Add Song To Queue </span>
- </button>
- <button
- class="button is-primary tab-actionable-button"
- v-if="
- sector === 'station' && loggedIn && station.type === 'official'
- "
- @click="openModal('requestSong')"
- >
- <i class="material-icons icon-with-button">queue</i>
- <span class="optional-desktop-only-text"> Request Song </span>
- </button>
- <button
- class="button is-primary tab-actionable-button disabled"
- v-if="
- sector === 'station' &&
- !loggedIn &&
- ((station.type === 'community' &&
- station.partyMode &&
- !station.locked) ||
- station.type === 'official')
- "
- content="Login to add songs to queue"
- v-tippy="{ theme: 'info' }"
- >
- <i class="material-icons icon-with-button">queue</i>
- <span class="optional-desktop-only-text"> Add Song To Queue </span>
- </button>
- <div
- id="queue-locked"
- v-if="station.type === 'community' && station.locked"
- >
- <button
- v-if="isAdminOnly() && !isOwnerOnly() && !dismissedWarning"
- class="button tab-actionable-button"
- @click="dismissedWarning = true"
- >
- THIS STATION'S QUEUE IS LOCKED.
- </button>
- <button
- v-if="!isAdminOnly() && !isOwnerOnly()"
- class="button tab-actionable-button"
- >
- THIS STATION'S QUEUE IS LOCKED.
- </button>
- </div>
- </div>
- </template>
- <script>
- import { mapActions, mapState, mapGetters } from "vuex";
- import draggable from "vuedraggable";
- import Toast from "toasters";
- import SongItem from "@/components/SongItem.vue";
- import Confirm from "@/components/Confirm.vue";
- export default {
- components: { draggable, SongItem, Confirm },
- props: {
- sector: {
- type: String,
- default: "station"
- }
- },
- data() {
- return {
- dismissedWarning: false,
- actionableButtonVisible: false,
- drag: false
- };
- },
- computed: {
- queue: {
- get() {
- if (this.sector === "manageStation")
- return this.$store.state.modals.manageStation.songsList;
- return this.$store.state.station.songsList;
- },
- set(queue) {
- if (this.sector === "manageStation")
- this.$store.commit(
- "modals/manageStation/updateSongsList",
- queue
- );
- else this.$store.commit("station/updateSongsList", queue);
- }
- },
- dragOptions() {
- return {
- animation: 200,
- group: "queue",
- disabled: !(this.isAdminOnly() || this.isOwnerOnly()),
- ghostClass: "draggable-list-ghost"
- };
- },
- ...mapState({
- loggedIn: state => state.user.auth.loggedIn,
- userId: state => state.user.auth.userId,
- userRole: state => state.user.auth.role,
- station(state) {
- return this.sector === "station"
- ? state.station.station
- : state.modals.manageStation.station;
- },
- songsList(state) {
- return this.sector === "station"
- ? state.station.songsList
- : state.modals.manageStation.songsList;
- },
- noSong: state => state.station.noSong
- }),
- ...mapGetters({
- socket: "websockets/getSocket"
- })
- },
- onUpdated() {
- // check if actionable button is visible, if not: set max-height of queue items to 100%
- if (
- document
- .getElementById("queue")
- .querySelectorAll(".tab-actionable-button").length > 0
- )
- this.actionableButtonVisible = true;
- else this.actionableButtonVisible = false;
- },
- methods: {
- isOwnerOnly() {
- return this.loggedIn && this.userId === this.station.owner;
- },
- isAdminOnly() {
- return this.loggedIn && this.userRole === "admin";
- },
- removeFromQueue(youtubeId) {
- this.socket.dispatch(
- "stations.removeFromQueue",
- this.station._id,
- youtubeId,
- res => {
- if (res.status === "success")
- new Toast("Successfully removed song from the queue.");
- else new Toast(res.message);
- }
- );
- },
- repositionSongInQueue({ moved }) {
- if (!moved) return; // we only need to update when song is moved
- this.socket.dispatch(
- "stations.repositionSongInQueue",
- this.station._id,
- {
- ...moved.element,
- oldIndex: moved.oldIndex,
- newIndex: moved.newIndex
- },
- res => {
- new Toast({ content: res.message, timeout: 4000 });
- if (res.status !== "success")
- this.repositionSongInList({
- ...moved.element,
- newIndex: moved.oldIndex,
- oldIndex: moved.newIndex
- });
- }
- );
- },
- moveSongToTop(song, index) {
- this.repositionSongInQueue({
- moved: {
- element: song,
- oldIndex: index,
- newIndex: 0
- }
- });
- },
- moveSongToBottom(song, index) {
- this.repositionSongInQueue({
- moved: {
- element: song,
- oldIndex: index,
- newIndex: this.songsList.length
- }
- });
- },
- ...mapActions({
- repositionSongInList(dispatch, payload) {
- if (this.sector === "manageStation")
- return dispatch(
- "modals/manageStation/repositionSongInList",
- payload
- );
- return dispatch("station/repositionSongInList", payload);
- }
- }),
- ...mapActions("modalVisibility", ["openModal"]),
- ...mapActions({
- showManageStationTab: "modals/manageStation/showTab"
- })
- }
- };
- </script>
- <style lang="scss" scoped>
- .night-mode {
- #queue {
- background-color: var(--dark-grey-3) !important;
- border: 0 !important;
- }
- }
- #queue {
- background-color: var(--white);
- border-radius: 0 0 5px 5px;
- .actionable-button-hidden {
- max-height: 100%;
- }
- .song-item:not(:last-of-type) {
- margin-bottom: 10px;
- }
- #queue-locked {
- display: flex;
- justify-content: center;
- }
- button.disabled {
- filter: grayscale(0.4);
- }
- }
- </style>
|