AzuraCast/frontend/vue/components/Stations/Media/MediaToolbar.vue

261 lines
10 KiB
Vue

<template>
<div class="row pt-4" id="app-toolbar">
<div class="col-md-8 buttons">
<div class="btn-group dropdown allow-focus">
<b-dropdown size="sm" variant="primary" ref="setPlaylistsDropdown" v-b-tooltip.hover
:title="langPlaylistDropdown">
<template #button-content>
<icon icon="clear_all"></icon>
{{ $gettext('Playlists') }}
<span class="caret"></span>
</template>
<b-dropdown-form class="pt-2" @submit.prevent="setPlaylists">
<div v-for="playlist in playlists" class="form-group">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input"
v-bind:id="'chk_playlist_' + playlist.id" name="playlists[]"
v-model="checkedPlaylists" v-bind:value="playlist.id">
<label class="custom-control-label" v-bind:for="'chk_playlist_'+playlist.id">
{{ playlist.name }}
</label>
</div>
</div>
<div class="form-group">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="chk_playlist_new"
v-model="checkedPlaylists" value="new">
<label class="custom-control-label" for="chk_playlist_new">
<input type="text" class="form-control p-2" id="new_playlist_name"
name="new_playlist_name" v-model="newPlaylist" style="min-width: 150px;"
:placeholder="langNewPlaylist">
</label>
</div>
</div>
<b-button type="submit" size="sm" variant="primary">
{{ $gettext('Save') }}
</b-button>
<b-button type="button" size="sm" variant="warning" @click="clearPlaylists()">
{{ $gettext('Clear') }}
</b-button>
</b-dropdown-form>
</b-dropdown>
</div>
<b-button size="sm" variant="primary" v-b-modal.move_file>
<icon icon="open_with"></icon>
{{ $gettext('Move') }}
</b-button>
<b-dropdown size="sm" variant="default">
<template #button-content>
<icon icon="more_horiz"></icon>
{{ langMore }}
</template>
<b-dropdown-item @click="doQueue" v-b-tooltip.hover :title="langQueue">
{{ $gettext('Queue') }}
</b-dropdown-item>
<b-dropdown-item v-if="supportsImmediateQueue" @click="doImmediateQueue" v-b-tooltip.hover
:title="langImmediateQueue">
{{ $gettext('Play Now') }}
</b-dropdown-item>
<b-dropdown-item @click="doReprocess" v-b-tooltip.hover :title="langReprocess">
{{ $gettext('Reprocess') }}
</b-dropdown-item>
</b-dropdown>
<b-button size="sm" variant="danger" @click="doDelete">
<icon icon="delete"></icon>
{{ $gettext('Delete') }}
</b-button>
</div>
<div class="col-md-4 text-right">
<b-button size="sm" variant="primary" v-b-modal.create_directory>
<icon icon="folder"></icon>
{{ $gettext('New Folder') }}
</b-button>
</div>
</div>
</template>
<script>
import _ from 'lodash';
import Icon from '~/components/Common/Icon';
import '~/vendor/sweetalert.js';
export default {
name: 'station-media-toolbar',
components: {Icon},
props: {
currentDirectory: String,
selectedItems: Object,
playlists: Array,
batchUrl: String,
supportsImmediateQueue: Boolean
},
data () {
return {
checkedPlaylists: [],
newPlaylist: '',
};
},
watch: {
selectedItems (items) {
// Get all playlists that are active on ALL selected items.
let playlistsForItems = _.map(items.all, (item) => {
return _.map(item.playlists, 'id');
});
// Check the checkboxes for those playlists.
this.checkedPlaylists = _.intersection(...playlistsForItems);
},
newPlaylist (text) {
if (text !== '') {
if (!this.checkedPlaylists.includes('new')) {
this.checkedPlaylists.push('new');
}
}
}
},
computed: {
langPlaylistDropdown() {
return this.$gettext('Set or clear playlists from the selected media');
},
langNewPlaylist() {
return this.$gettext('New Playlist');
},
langMore() {
return this.$gettext('More');
},
langImmediateQueue() {
return this.$gettext('Make the selected media play immediately, interrupting existing media');
},
langQueue() {
return this.$gettext('Queue the selected media to play next');
},
langReprocess() {
return this.$gettext('Analyze and reprocess the selected media');
},
langErrors() {
return this.$gettext('The request could not be processed.');
},
},
methods: {
doImmediateQueue() {
this.doBatch('immediate', this.$gettext('Files played immediately:'));
},
doQueue() {
this.doBatch('queue', this.$gettext('Files queued for playback:'));
},
doReprocess() {
this.doBatch('reprocess', this.$gettext('Files marked for reprocessing:'));
},
doDelete() {
let buttonConfirmText = this.$gettext('Delete %{ num } media files?');
let numFiles = this.selectedItems.all.length;
this.$confirmDelete({
title: this.$gettextInterpolate(buttonConfirmText, {num: numFiles}),
}).then((result) => {
if (result.value) {
this.doBatch('delete', this.$gettext('Files removed:'));
}
});
},
doBatch (action, notifyMessage) {
if (this.selectedItems.all.length) {
this.$wrapWithLoading(
this.axios.put(this.batchUrl, {
'do': action,
'current_directory': this.currentDirectory,
'files': this.selectedItems.files,
'dirs': this.selectedItems.directories
})
).then((resp) => {
if (resp.data.success) {
let allItemNodes = [];
_.forEach(this.selectedItems.all, (item) => {
allItemNodes.push(this.$createElement('div', {}, item.path_short));
});
this.$notifySuccess(allItemNodes, {
title: notifyMessage
});
} else {
let errorNodes = [];
_.forEach(resp.data.errors, (error) => {
errorNodes.push(this.$createElement('div', {}, error));
});
this.$notifyError(errorNodes, {
title: this.langErrors
});
}
this.$emit('relist');
});
} else {
this.notifyNoFiles();
}
},
clearPlaylists () {
this.checkedPlaylists = [];
this.newPlaylist = '';
this.setPlaylists();
},
setPlaylists () {
this.$refs.setPlaylistsDropdown.hide();
if (this.selectedItems.all.length) {
this.$wrapWithLoading(
this.axios.put(this.batchUrl, {
'do': 'playlist',
'playlists': this.checkedPlaylists,
'new_playlist_name': this.newPlaylist,
'currentDirectory': this.currentDirectory,
'files': this.selectedItems.files,
'dirs': this.selectedItems.directories
})
).then((resp) => {
if (resp.data.success) {
if (resp.data.record) {
this.$emit('add-playlist', resp.data.record);
}
let notifyMessage = (this.checkedPlaylists.length > 0)
? this.$gettext('Playlists updated for selected files:')
: this.$gettext('Playlists cleared for selected files:');
let allItemNodes = [];
_.forEach(this.selectedItems.all, (item) => {
allItemNodes.push(this.$createElement('div', {}, item.path_short));
});
this.$notifySuccess(allItemNodes, {
title: notifyMessage
});
this.checkedPlaylists = [];
this.newPlaylist = '';
} else {
let errorNodes = [];
_.forEach(resp.data.errors, (error) => {
errorNodes.push(this.$createElement('div', {}, error));
});
this.$notifyError(errorNodes, {
title: this.langErrors
});
}
this.$emit('relist');
});
} else {
this.notifyNoFiles();
}
},
notifyNoFiles() {
this.$notifyError(this.$gettext('No files selected.'));
}
}
};
</script>