4
0
mirror of https://github.com/AzuraCast/AzuraCast.git synced 2024-06-14 05:06:37 +00:00
AzuraCast/frontend/vue/components/Stations/Media/MediaToolbar.vue
2023-01-06 19:55:08 -06:00

336 lines
12 KiB
Vue

<template>
<div
id="app-toolbar"
class="row pt-4"
>
<div class="col-md-8 buttons">
<div class="btn-group dropdown allow-focus">
<b-dropdown
ref="setPlaylistsDropdown"
v-b-tooltip.hover
size="sm"
variant="primary"
:title="$gettext('Set or clear playlists from the selected media')"
>
<template #button-content>
<icon icon="clear_all" />
{{ $gettext('Playlists') }}
<span class="caret" />
</template>
<b-dropdown-form
class="pt-2"
@submit.prevent="setPlaylists"
>
<div
v-for="playlist in playlists"
:key="playlist.id"
class="form-group"
>
<div class="custom-control custom-checkbox">
<input
:id="'chk_playlist_' + playlist.id"
v-model="checkedPlaylists"
type="checkbox"
class="custom-control-input"
name="playlists[]"
:value="playlist.id"
>
<label
class="custom-control-label"
:for="'chk_playlist_'+playlist.id"
>
{{ playlist.name }}
</label>
</div>
</div>
<div class="form-group">
<div class="custom-control custom-checkbox">
<input
id="chk_playlist_new"
v-model="checkedPlaylists"
type="checkbox"
class="custom-control-input"
value="new"
>
<label
class="custom-control-label"
for="chk_playlist_new"
>
<input
id="new_playlist_name"
v-model="newPlaylist"
type="text"
class="form-control p-2"
name="new_playlist_name"
style="min-width: 150px;"
:placeholder="$gettext('New Playlist')"
>
</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
v-b-modal.move_file
size="sm"
variant="primary"
>
<icon icon="open_with" />
{{ $gettext('Move') }}
</b-button>
<b-dropdown
size="sm"
variant="default"
>
<template #button-content>
<icon icon="more_horiz" />
{{ $gettext('More') }}
</template>
<b-dropdown-item
v-b-tooltip.hover
:title="$gettext('Queue the selected media to play next')"
@click="doQueue"
>
{{ $gettext('Queue') }}
</b-dropdown-item>
<b-dropdown-item
v-if="supportsImmediateQueue"
v-b-tooltip.hover
:title="$gettext('Make the selected media play immediately, interrupting existing media')"
@click="doImmediateQueue"
>
{{ $gettext('Play Now') }}
</b-dropdown-item>
<b-dropdown-item
v-b-tooltip.hover
:title="$gettext('Analyze and reprocess the selected media')"
@click="doReprocess"
>
{{ $gettext('Reprocess') }}
</b-dropdown-item>
</b-dropdown>
<b-button
size="sm"
variant="danger"
@click="doDelete"
>
<icon icon="delete" />
{{ $gettext('Delete') }}
</b-button>
</div>
<div class="col-md-4 text-right">
<b-button
v-b-modal.create_directory
size="sm"
variant="primary"
>
<icon icon="folder" />
{{ $gettext('New Folder') }}
</b-button>
</div>
</div>
</template>
<script>
import {forEach, intersection, map} from 'lodash';
import Icon from '~/components/Common/Icon';
import '~/vendor/sweetalert';
/* TODO Options API */
export default {
name: 'StationMediaToolbar',
components: {Icon},
props: {
currentDirectory: {
type: String,
required: true
},
selectedItems: {
type: Object,
required: true
},
playlists: {
type: Array,
default: () => {
return [];
}
},
batchUrl: {
type: String,
required: true
},
supportsImmediateQueue: {
type: Boolean,
required: true
}
},
emits: ['relist', 'add-playlist'],
data() {
return {
checkedPlaylists: [],
newPlaylist: '',
};
},
computed: {
langErrors() {
return this.$gettext('The request could not be processed.');
},
},
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');
}
}
}
},
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>