More Composition conversion and fixes.

This commit is contained in:
Buster Neece 2023-01-07 10:04:08 -06:00
parent 1ef68f64fc
commit e0f5178ba4
No known key found for this signature in database
GPG Key ID: F1D2E64A0005E80E
10 changed files with 535 additions and 540 deletions

View File

@ -106,4 +106,8 @@ const update = () => {
}
onMounted(update);
defineExpose({
update
});
</script>

View File

@ -6,7 +6,7 @@
<div class="col-md-8 buttons">
<div class="btn-group dropdown allow-focus">
<b-dropdown
ref="setPlaylistsDropdown"
ref="$setPlaylistsDropdown"
v-b-tooltip.hover
size="sm"
variant="primary"
@ -69,21 +69,23 @@
</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>
<div class="buttons">
<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>
</div>
</b-dropdown-form>
</b-dropdown>
</div>
@ -148,188 +150,200 @@
</div>
</div>
</template>
<script>
<script setup>
import {forEach, intersection, map} from 'lodash';
import Icon from '~/components/Common/Icon';
import '~/vendor/sweetalert';
import {h, ref, toRef, watch} from "vue";
import {useTranslate} from "~/vendor/gettext";
import {useNotify} from "~/vendor/bootstrapVue";
import {useAxios} from "~/vendor/axios";
import {useSweetAlert} from "~/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
const props = defineProps({
currentDirectory: {
type: String,
required: true
},
selectedItems: {
type: Object,
required: true
},
playlists: {
type: Array,
default: () => {
return [];
}
},
emits: ['relist', 'add-playlist'],
data() {
return {
checkedPlaylists: [],
newPlaylist: '',
};
batchUrl: {
type: String,
required: true
},
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');
});
supportsImmediateQueue: {
type: Boolean,
required: true
}
});
// 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;
const emit = defineEmits(['relist', 'add-playlist']);
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));
});
const checkedPlaylists = ref([]);
const newPlaylist = ref('');
this.$notifySuccess(allItemNodes, {
title: notifyMessage
});
} else {
let errorNodes = [];
forEach(resp.data.errors, (error) => {
errorNodes.push(this.$createElement('div', {}, error));
});
const {$gettext} = useTranslate();
const langErrors = $gettext('The request could not be processed.');
this.$notifyError(errorNodes, {
title: this.langErrors
});
}
watch(toRef(props, 'selectedItems'), (items) => {
// Get all playlists that are active on ALL selected items.
let playlistsForItems = map(items.all, (item) => {
return map(item.playlists, 'id');
});
this.$emit('relist');
});
} else {
this.notifyNoFiles();
}
},
clearPlaylists () {
this.checkedPlaylists = [];
this.newPlaylist = '';
// Check the checkboxes for those playlists.
checkedPlaylists.value = intersection(...playlistsForItems);
});
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.'));
watch(newPlaylist, (text) => {
if (text !== '') {
if (!checkedPlaylists.value.includes('new')) {
checkedPlaylists.value.push('new');
}
}
});
const {wrapWithLoading, notifySuccess, notifyError} = useNotify();
const {axios} = useAxios();
const notifyNoFiles = () => {
notifyError($gettext('No files selected.'));
};
const doBatch = (action, notifyMessage) => {
if (props.selectedItems.all.length) {
wrapWithLoading(
axios.put(props.batchUrl, {
'do': action,
'current_directory': props.currentDirectory,
'files': props.selectedItems.files,
'dirs': props.selectedItems.directories
})
).then((resp) => {
if (resp.data.success) {
let allItemNodes = [];
forEach(props.selectedItems.all, (item) => {
allItemNodes.push(h('div', {}, item.path_short));
});
notifySuccess(allItemNodes, {
title: notifyMessage
});
} else {
let errorNodes = [];
forEach(resp.data.errors, (error) => {
errorNodes.push(h('div', {}, error));
});
notifyError(errorNodes, {
title: langErrors
});
}
emit('relist');
});
} else {
notifyNoFiles();
}
};
const doImmediateQueue = () => {
doBatch('immediate', $gettext('Files played immediately:'));
};
const doQueue = () => {
doBatch('queue', $gettext('Files queued for playback:'));
};
const doReprocess = () => {
doBatch('reprocess', $gettext('Files marked for reprocessing:'));
};
const {confirmDelete} = useSweetAlert();
const doDelete = () => {
let numFiles = this.selectedItems.all.length;
let buttonConfirmText = $gettext(
'Delete %{ num } media files?',
{num: numFiles}
);
confirmDelete({
title: buttonConfirmText,
}).then((result) => {
if (result.value) {
doBatch('delete', $gettext('Files removed:'));
}
});
};
const $setPlaylistsDropdown = ref(); // Template Ref
const setPlaylists = () => {
$setPlaylistsDropdown.value.hide();
if (props.selectedItems.all.length) {
wrapWithLoading(
axios.put(props.batchUrl, {
'do': 'playlist',
'playlists': checkedPlaylists.value,
'new_playlist_name': newPlaylist.value,
'currentDirectory': props.currentDirectory,
'files': props.selectedItems.files,
'dirs': props.selectedItems.directories
})
).then((resp) => {
if (resp.data.success) {
if (resp.data.record) {
emit('add-playlist', resp.data.record);
}
let notifyMessage = (checkedPlaylists.value.length > 0)
? $gettext('Playlists updated for selected files:')
: $gettext('Playlists cleared for selected files:');
let allItemNodes = [];
forEach(props.selectedItems.all, (item) => {
allItemNodes.push(h('div', {}, item.path_short));
});
notifySuccess(allItemNodes, {
title: notifyMessage
});
checkedPlaylists.value = [];
newPlaylist.value = '';
} else {
let errorNodes = [];
forEach(resp.data.errors, (error) => {
errorNodes.push(h('div', {}, error));
});
notifyError(errorNodes, {
title: langErrors
});
}
emit('relist');
});
} else {
notifyNoFiles();
}
};
const clearPlaylists = () => {
checkedPlaylists.value = [];
newPlaylist.value = '';
setPlaylists();
};
</script>

View File

@ -14,7 +14,7 @@
size="sm"
variant="outline-light"
class="py-2 pr-0"
@click.prevent="$emit('remove')"
@click.prevent="doRemove()"
>
<icon icon="remove" />
{{ $gettext('Remove') }}
@ -27,7 +27,7 @@
<b-wrapped-form-group
:id="'edit_form_start_time_'+index"
class="col-md-4"
:field="v$.row.start_time"
:field="v$.start_time"
>
<template #label>
{{ $gettext('Start Time') }}
@ -47,7 +47,7 @@
<b-wrapped-form-group
:id="'edit_form_end_time_'+index"
class="col-md-4"
:field="v$.row.end_time"
:field="v$.end_time"
>
<template #label>
{{ $gettext('End Time') }}
@ -81,7 +81,7 @@
<b-wrapped-form-group
:id="'edit_form_start_date_'+index"
class="col-md-4"
:field="v$.row.start_date"
:field="v$.start_date"
>
<template #label>
{{ $gettext('Start Date') }}
@ -104,7 +104,7 @@
<b-wrapped-form-group
:id="'edit_form_end_date_'+index"
class="col-md-4"
:field="v$.row.end_date"
:field="v$.end_date"
>
<template #label>
{{ $gettext('End Date') }}
@ -122,7 +122,7 @@
<b-wrapped-form-checkbox
:id="'edit_form_loop_once_'+index"
class="col-md-4"
:field="v$.row.loop_once"
:field="v$.loop_once"
>
<template #label>
{{ $gettext('Loop Once') }}
@ -146,7 +146,7 @@
<template #default>
<b-checkbox-group
:id="'edit_form_days_'+index"
v-model="v$.row.days.$model"
v-model="v$.days.$model"
stacked
:options="dayOptions"
/>
@ -158,59 +158,56 @@
</b-card>
</template>
<script>
<script setup>
import PlaylistTime from '~/components/Common/TimeCode';
import Icon from "~/components/Common/Icon.vue";
import BWrappedFormGroup from "~/components/Form/BWrappedFormGroup.vue";
import {required} from "@vuelidate/validators";
import useVuelidate from "@vuelidate/core";
import BWrappedFormCheckbox from "~/components/Form/BWrappedFormCheckbox.vue";
import {toRef} from "vue";
import {useTranslate} from "~/vendor/gettext";
/* TODO Options API */
const props = defineProps({
index: {
type: Number,
required: true
},
row: {
type: Object,
required: true
},
stationTimeZone: {
type: String,
required: true
},
});
export default {
name: 'PlaylistsFormScheduleRow',
components: {BWrappedFormCheckbox, BWrappedFormGroup, Icon, PlaylistTime},
props: {
index: {
type: Number,
required: true
},
row: {
type: Object,
required: true
},
stationTimeZone: {
type: String,
required: true
},
const emit = defineEmits(['remove']);
const v$ = useVuelidate(
{
'start_time': {required},
'end_time': {required},
'start_date': {},
'end_date': {},
'loop_once': {}
},
emits: ['remove'],
setup() {
return {v$: useVuelidate()}
},
validations: {
row: {
'start_time': {required},
'end_time': {required},
'start_date': {},
'end_date': {},
'days': {},
'loop_once': {}
}
},
data() {
return {
dayOptions: [
{value: 1, text: this.$gettext('Monday')},
{value: 2, text: this.$gettext('Tuesday')},
{value: 3, text: this.$gettext('Wednesday')},
{value: 4, text: this.$gettext('Thursday')},
{value: 5, text: this.$gettext('Friday')},
{value: 6, text: this.$gettext('Saturday')},
{value: 7, text: this.$gettext('Sunday')}
]
};
},
}
toRef(props, 'row')
);
const {$gettext} = useTranslate();
const dayOptions = [
{value: 1, text: $gettext('Monday')},
{value: 2, text: $gettext('Tuesday')},
{value: 3, text: $gettext('Wednesday')},
{value: 4, text: $gettext('Thursday')},
{value: 5, text: $gettext('Friday')},
{value: 6, text: $gettext('Saturday')},
{value: 7, text: $gettext('Sunday')}
];
const doRemove = () => {
emit('remove');
};
</script>

View File

@ -22,7 +22,7 @@
class="text-right text-white-50"
>
<stations-common-quota
ref="quota"
ref="$quota"
:quota-url="quotaUrl"
/>
</b-col>
@ -54,7 +54,7 @@
<data-table
id="station_podcast_episodes"
ref="datatable"
ref="$datatable"
paginated
:fields="fields"
:responsive="false"
@ -107,7 +107,7 @@
</b-card>
<edit-modal
ref="editEpisodeModal"
ref="$editEpisodeModal"
:create-url="podcast.links.episodes"
:station-time-zone="stationTimeZone"
:new-art-url="podcast.links.episode_new_art"
@ -118,68 +118,77 @@
/>
</template>
<script>
<script setup>
import DataTable from '~/components/Common/DataTable';
import EditModal from './EpisodeEditModal';
import Icon from '~/components/Common/Icon';
import AlbumArt from '~/components/Common/AlbumArt';
import StationsCommonQuota from "~/components/Stations/Common/Quota";
import episodesViewProps from "~/components/Stations/Podcasts/episodesViewProps";
import {useTranslate} from "~/vendor/gettext";
import {ref} from "vue";
import {useSweetAlert} from "~/vendor/sweetalert";
import {useNotify} from "~/vendor/bootstrapVue";
import {useAxios} from "~/vendor/axios";
/* TODO Options API */
const props = defineProps({
...episodesViewProps,
podcast: {
type: Object,
required: true
}
});
export default {
name: 'EpisodesView',
components: {StationsCommonQuota, AlbumArt, Icon, EditModal, DataTable},
props: {
...episodesViewProps,
podcast: {
type: Object,
required: true
}
},
emits: ['clear-podcast'],
data() {
return {
fields: [
{key: 'art', label: this.$gettext('Art'), sortable: false, class: 'shrink pr-0'},
{key: 'title', label: this.$gettext('Episode'), sortable: false},
{key: 'podcast_media', label: this.$gettext('File Name'), sortable: false},
{key: 'explicit', label: this.$gettext('Explicit'), sortable: false},
{key: 'actions', label: this.$gettext('Actions'), sortable: false, class: 'shrink'}
]
};
},
methods: {
relist () {
this.$refs.quota.update();
if (this.$refs.datatable) {
this.$refs.datatable.refresh();
}
},
doCreate () {
this.$refs.editEpisodeModal.create();
},
doEdit (url) {
this.$refs.editEpisodeModal.edit(url);
},
doClearPodcast () {
this.$emit('clear-podcast');
},
doDelete (url) {
this.$confirmDelete({
title: this.$gettext('Delete Episode?'),
}).then((result) => {
if (result.value) {
this.$wrapWithLoading(
this.axios.delete(url)
).then((resp) => {
this.$notifySuccess(resp.data.message);
this.relist();
});
}
const emit = defineEmits(['clear-podcast']);
const {$gettext} = useTranslate();
const fields = [
{key: 'art', label: $gettext('Art'), sortable: false, class: 'shrink pr-0'},
{key: 'title', label: $gettext('Episode'), sortable: false},
{key: 'podcast_media', label: $gettext('File Name'), sortable: false},
{key: 'explicit', label: $gettext('Explicit'), sortable: false},
{key: 'actions', label: $gettext('Actions'), sortable: false, class: 'shrink'}
];
const $quota = ref(); // Template Ref
const $datatable = ref(); // Template Ref
const relist = () => {
$quota.value.update();
$datatable.value?.refresh();
};
const $editEpisodeModal = ref(); // Template Ref
const doCreate = () => {
$editEpisodeModal.value.create();
};
const doEdit = (url) => {
$editEpisodeModal.value.edit(url);
};
const doClearPodcast = () => {
emit('clear-podcast');
};
const {confirmDelete} = useSweetAlert();
const {wrapWithLoading, notifySuccess} = useNotify();
const {axios} = useAxios();
const doDelete = (url) => {
confirmDelete({
title: $gettext('Delete Episode?'),
}).then((result) => {
if (result.value) {
wrapWithLoading(
axios.delete(url)
).then((resp) => {
notifySuccess(resp.data.message);
relist();
});
}
}
});
};
</script>

View File

@ -12,7 +12,7 @@
class="text-right text-white-50"
>
<stations-common-quota
ref="quota"
ref="$quota"
:quota-url="quotaUrl"
/>
</b-col>
@ -36,7 +36,7 @@
<data-table
id="station_podcasts"
ref="datatable"
ref="$datatable"
paginated
:fields="fields"
:responsive="false"
@ -58,9 +58,6 @@
target="_blank"
>{{ $gettext('RSS Feed') }}</a>
</template>
<template #cell(num_episodes)="row">
{{ countEpisodes(row.item.episodes) }}
</template>
<template #cell(actions)="row">
<b-button-group size="sm">
<b-button
@ -90,7 +87,7 @@
</b-card>
<edit-modal
ref="editPodcastModal"
ref="$editPodcastModal"
:create-url="listUrl"
:station-time-zone="stationTimeZone"
:new-art-url="newArtUrl"
@ -100,65 +97,78 @@
/>
</template>
<script>
<script setup>
import DataTable from '~/components/Common/DataTable';
import EditModal from './PodcastEditModal';
import AlbumArt from '~/components/Common/AlbumArt';
import StationsCommonQuota from "~/components/Stations/Common/Quota";
import listViewProps from "./listViewProps";
import {useTranslate} from "~/vendor/gettext";
import {ref} from "vue";
import {useSweetAlert} from "~/vendor/sweetalert";
import {useNotify} from "~/vendor/bootstrapVue";
import {useAxios} from "~/vendor/axios";
/* TODO Options API */
const props = defineProps({
...listViewProps
});
export default {
name: 'ListView',
components: {StationsCommonQuota, AlbumArt, EditModal, DataTable},
props: {
...listViewProps
const emit = defineEmits(['select-podcast']);
const {$gettext} = useTranslate();
const fields = [
{key: 'art', label: $gettext('Art'), sortable: false, class: 'shrink pr-0'},
{key: 'title', label: $gettext('Podcast'), sortable: false},
{
key: 'episodes',
label: $gettext('# Episodes'),
sortable: false,
formatter: (val) => {
return val.length;
}
},
emits: ['select-podcast'],
data() {
return {
fields: [
{key: 'art', label: this.$gettext('Art'), sortable: false, class: 'shrink pr-0'},
{key: 'title', label: this.$gettext('Podcast'), sortable: false},
{key: 'num_episodes', label: this.$gettext('# Episodes'), sortable: false},
{key: 'actions', label: this.$gettext('Actions'), sortable: false, class: 'shrink'}
]
};
},
methods: {
countEpisodes (episodes) {
return episodes.length;
},
relist () {
this.$refs.quota.update();
if (this.$refs.datatable) {
this.$refs.datatable.refresh();
}
},
doCreate () {
this.$refs.editPodcastModal.create();
},
doEdit (url) {
this.$refs.editPodcastModal.edit(url);
},
doSelectPodcast (podcast) {
this.$emit('select-podcast', podcast);
},
doDelete (url) {
this.$confirmDelete({
title: this.$gettext('Delete Podcast?'),
}).then((result) => {
if (result.value) {
this.$wrapWithLoading(
this.axios.delete(url)
).then((resp) => {
this.$notifySuccess(resp.data.message);
this.relist();
});
}
{key: 'actions', label: $gettext('Actions'), sortable: false, class: 'shrink'}
];
const $quota = ref(); // Template Ref
const $datatable = ref(); // Template Ref
const relist = () => {
$quota.value.update();
$datatable.value?.refresh();
};
const $editPodcastModal = ref(); // Template Ref
const doCreate = () => {
$editPodcastModal.value.create();
};
const doEdit = (url) => {
$editPodcastModal.value.edit(url);
};
const doSelectPodcast = (podcast) => {
emit('select-podcast', podcast);
};
const {confirmDelete} = useSweetAlert();
const {wrapWithLoading, notifySuccess} = useNotify();
const {axios} = useAxios();
const doDelete = (url) => {
confirmDelete({
title: $gettext('Delete Podcast?'),
}).then((result) => {
if (result.value) {
wrapWithLoading(
axios.delete(url)
).then((resp) => {
notifySuccess(resp.data.message);
relist();
});
}
}
});
};
</script>

View File

@ -132,74 +132,57 @@
</b-tab>
</template>
<script>
<script setup>
import BWrappedFormGroup from "~/components/Form/BWrappedFormGroup";
import BWrappedFormCheckbox from "~/components/Form/BWrappedFormCheckbox";
import {map} from "lodash";
import {computed} from "vue";
/* TODO Options API */
export default {
name: 'RemoteFormAutoDj',
components: {BWrappedFormCheckbox, BWrappedFormGroup},
props: {
form: {
type: Object,
required: true
},
stationFrontendType: {
type: String,
required: true
}
const props = defineProps({
form: {
type: Object,
required: true
},
computed: {
formatOptions() {
return [
{
value: 'mp3',
text: 'MP3'
},
{
value: 'ogg',
text: 'OGG Vorbis'
},
{
value: 'opus',
text: 'OGG Opus'
},
{
value: 'aac',
text: 'AAC+ (MPEG4 HE-AAC v2)'
},
{
value: 'flac',
text: 'FLAC (OGG FLAC)'
}
];
},
bitrateOptions() {
let options = [];
[32, 48, 64, 96, 128, 192, 256, 320].forEach((val) => {
options.push({
value: val,
text: val
});
});
return options;
},
formatSupportsBitrateOptions() {
switch (this.form.autodj_format.$model) {
case 'flac':
return false;
case 'mp3':
case 'ogg':
case 'opus':
case 'aac':
default:
return true;
}
}
stationFrontendType: {
type: String,
required: true
}
};
});
const formatOptions = [
{
value: 'mp3',
text: 'MP3'
},
{
value: 'ogg',
text: 'OGG Vorbis'
},
{
value: 'opus',
text: 'OGG Opus'
},
{
value: 'aac',
text: 'AAC+ (MPEG4 HE-AAC v2)'
},
{
value: 'flac',
text: 'FLAC (OGG FLAC)'
}
];
const bitrateOptions = map(
[32, 48, 64, 96, 128, 192, 256, 320],
(val) => {
return {
value: val,
text: val
};
}
);
const formatSupportsBitrateOptions = computed(() => {
return props.form.autodj_format.$model !== 'flac';
});
</script>

View File

@ -103,39 +103,30 @@
</b-tab>
</template>
<script>
<script setup>
import {REMOTE_ICECAST, REMOTE_SHOUTCAST1, REMOTE_SHOUTCAST2} from '~/components/Entity/RadioAdapters';
import BWrappedFormGroup from "~/components/Form/BWrappedFormGroup";
import BWrappedFormCheckbox from "~/components/Form/BWrappedFormCheckbox";
/* TODO Options API */
export default {
name: 'RemoteFormBasicInfo',
components: {BWrappedFormCheckbox, BWrappedFormGroup},
props: {
form: {
type: Object,
required: true
}
},
computed: {
typeOptions() {
return [
{
value: REMOTE_ICECAST,
text: 'Icecast v2.4+',
},
{
value: REMOTE_SHOUTCAST1,
text: 'Shoutcast v1',
},
{
value: REMOTE_SHOUTCAST2,
text: 'Shoutcast v2',
}
];
},
const props = defineProps({
form: {
type: Object,
required: true
}
};
});
const typeOptions = [
{
value: REMOTE_ICECAST,
text: 'Icecast v2.4+',
},
{
value: REMOTE_SHOUTCAST1,
text: 'Shoutcast v1',
},
{
value: REMOTE_SHOUTCAST2,
text: 'Shoutcast v2',
}
];
</script>

View File

@ -86,6 +86,7 @@ import {computed, ref} from "vue";
import {useTranslate} from "~/vendor/gettext";
import {useSweetAlert} from "~/vendor/sweetalert";
import {useNotify} from "~/vendor/bootstrapVue";
import {useAxios} from "~/vendor/axios";
const props = defineProps({
listUrl: {
@ -150,6 +151,7 @@ const formatTime = (time) => {
const {confirmDelete} = useSweetAlert();
const {wrapWithLoading, notifySuccess} = useNotify();
const {axios} = useAxios();
const doDelete = (url) => {
confirmDelete({

View File

@ -64,7 +64,7 @@
<b-wrapped-form-group
id="form_start_date"
name="start_date"
:field="v$.form.start_date"
:field="v$.start_date"
input-type="date"
>
<template #label>
@ -75,7 +75,7 @@
<b-wrapped-form-group
id="form_end_date"
name="end_date"
:field="v$.form.end_date"
:field="v$.end_date"
input-type="date"
>
<template #label>
@ -86,7 +86,7 @@
<b-wrapped-form-checkbox
id="form_edit_fetch_isrc"
name="fetch_isrc"
:field="v$.form.fetch_isrc"
:field="v$.fetch_isrc"
>
<template #label>
{{ $gettext('Attempt to Automatically Retrieve ISRC When Missing') }}
@ -102,7 +102,7 @@
<b-button
type="submit"
size="lg"
:variant="(v$.form.$invalid) ? 'danger' : 'primary'"
:variant="(v$.$invalid) ? 'danger' : 'primary'"
class="mt-2"
>
{{ $gettext('Generate Report') }}
@ -112,52 +112,38 @@
</section>
</template>
<script>
import useVuelidate from "@vuelidate/core";
<script setup>
import {required} from '@vuelidate/validators';
import BWrappedFormGroup from "~/components/Form/BWrappedFormGroup";
import BFormFieldset from "~/components/Form/BFormFieldset";
import BWrappedFormCheckbox from "~/components/Form/BWrappedFormCheckbox";
import {useVuelidateOnForm} from "~/functions/useVuelidateOnForm";
/* TODO Options API */
export default {
name: 'StationsReportsSoundExchange',
components: {BWrappedFormGroup, BFormFieldset, BWrappedFormCheckbox},
props: {
apiUrl: {
type: String,
required: true
},
startDate: {
type: String,
required: true
},
endDate: {
type: String,
required: true
}
const props = defineProps({
apiUrl: {
type: String,
required: true
},
setup() {
return {v$: useVuelidate()}
startDate: {
type: String,
required: true
},
validations() {
return {
form: {
start_date: {required},
end_date: {required},
fetch_isrc: {}
}
}
},
data() {
return {
form: {
start_date: this.startDate,
end_date: this.endDate,
fetch_isrc: false
}
}
endDate: {
type: String,
required: true
}
}
});
const {v$} = useVuelidateOnForm(
{
start_date: {required},
end_date: {required},
fetch_isrc: {}
},
{
start_date: props.startDate,
end_date: props.endDate,
fetch_isrc: false
}
);
</script>

View File

@ -14,7 +14,7 @@
size="sm"
variant="outline-light"
class="py-2 pr-0"
@click.prevent="$emit('remove')"
@click.prevent="doRemove()"
>
<icon icon="remove" />
{{ $gettext('Remove') }}
@ -27,7 +27,7 @@
<b-wrapped-form-group
:id="'edit_form_start_time_'+index"
class="col-md-4"
:field="v$.row.start_time"
:field="v$.start_time"
>
<template #label>
{{ $gettext('Start Time') }}
@ -44,7 +44,7 @@
<b-wrapped-form-group
:id="'edit_form_end_time_'+index"
class="col-md-4"
:field="v$.row.end_time"
:field="v$.end_time"
>
<template #label>
{{ $gettext('End Time') }}
@ -78,7 +78,7 @@
<b-wrapped-form-group
:id="'edit_form_start_date_'+index"
class="col-md-4"
:field="v$.row.start_date"
:field="v$.start_date"
input-type="date"
>
<template #label>
@ -94,7 +94,7 @@
<b-wrapped-form-group
:id="'edit_form_end_date_'+index"
class="col-md-4"
:field="v$.row.end_date"
:field="v$.end_date"
input-type="date"
>
<template #label>
@ -105,7 +105,7 @@
<b-wrapped-form-group
:id="'edit_form_days_'+index"
class="col-md-4"
:field="v$.row.days"
:field="v$.days"
>
<template #label>
{{ $gettext('Scheduled Play Days of Week') }}
@ -128,57 +128,56 @@
</b-card>
</template>
<script>
<script setup>
import PlaylistTime from '~/components/Common/TimeCode';
import Icon from "~/components/Common/Icon.vue";
import BWrappedFormGroup from "~/components/Form/BWrappedFormGroup.vue";
import {required} from "@vuelidate/validators";
import useVuelidate from "@vuelidate/core";
import {toRef} from "vue";
import {useTranslate} from "~/vendor/gettext";
/* TODO Options API */
const props = defineProps({
index: {
type: Number,
required: true
},
row: {
type: Object,
required: true
},
stationTimeZone: {
type: String,
required: true
},
});
export default {
name: 'StreamersFormScheduleRow',
components: {BWrappedFormGroup, Icon, PlaylistTime},
props: {
index: {
type: Number,
required: true
},
row: {
type: Object,
required: true
},
stationTimeZone: {
type: String,
required: true
},
const emit = defineEmits(['remove']);
const v$ = useVuelidate(
{
'start_time': {required},
'end_time': {required},
'start_date': {},
'end_date': {},
'days': {}
},
emits: ['remove'],
setup() {
return {v$: useVuelidate()}
},
validations: {
row: {
'start_time': {required},
'end_time': {required},
'start_date': {},
'end_date': {},
'days': {}
}
},
data() {
return {
dayOptions: [
{value: 1, text: this.$gettext('Monday')},
{value: 2, text: this.$gettext('Tuesday')},
{value: 3, text: this.$gettext('Wednesday')},
{value: 4, text: this.$gettext('Thursday')},
{value: 5, text: this.$gettext('Friday')},
{value: 6, text: this.$gettext('Saturday')},
{value: 7, text: this.$gettext('Sunday')}
]
};
},
}
toRef(props, 'row')
);
const {$gettext} = useTranslate();
const dayOptions = [
{value: 1, text: $gettext('Monday')},
{value: 2, text: $gettext('Tuesday')},
{value: 3, text: $gettext('Wednesday')},
{value: 4, text: $gettext('Thursday')},
{value: 5, text: $gettext('Friday')},
{value: 6, text: $gettext('Saturday')},
{value: 7, text: $gettext('Sunday')}
];
const doRemove = () => {
emit('remove');
};
</script>