Vue fixes and Composition API updates.

This commit is contained in:
Buster Neece 2023-01-06 19:05:40 -06:00
parent 10c8069719
commit f15ef56f6d
No known key found for this signature in database
GPG Key ID: F1D2E64A0005E80E
19 changed files with 547 additions and 574 deletions

View File

@ -34,9 +34,6 @@
:fields="fields"
:api-url="apiUrl"
>
<template #cell(owner)="row">
{{ row.item.user.email }}
</template>
<template #cell(actions)="row">
<b-button-group size="sm">
<b-button
@ -83,7 +80,7 @@ const fields = ref([
sortable: false
},
{
key: 'owner',
key: 'user.email',
label: $gettext('Owner'),
sortable: false
},

View File

@ -112,12 +112,6 @@
:fields="fields"
:api-url="listUrl"
>
<template #cell(timestamp)="row">
{{ toLocaleTime(row.item.timestamp) }}
</template>
<template #cell(size)="row">
{{ formatFileSize(row.item.size) }}
</template>
<template #cell(actions)="row">
<b-button-group size="sm">
<b-button
@ -211,6 +205,7 @@ const blankSettings = {
const settings = ref({...blankSettings});
const {$gettext} = useTranslate();
const {timeConfig} = useAzuraCast();
const fields = [
{
@ -222,12 +217,18 @@ const fields = [
{
key: 'timestamp',
label: $gettext('Last Modified'),
sortable: false
sortable: false,
formatter: (value) => {
return DateTime.fromSeconds(value).toLocaleString(
{...DateTime.DATETIME_SHORT, ...timeConfig}
);
}
},
{
key: 'size',
label: $gettext('Size'),
sortable: false
sortable: false,
formatter: (value) => formatFileSize(value)
},
{
key: 'actions',
@ -264,14 +265,6 @@ const toRelativeTime = (timestamp) => {
return DateTime.fromSeconds(timestamp).toRelative();
};
const toLocaleTime = (timestamp) => {
const {timeConfig} = useAzuraCast();
return DateTime.fromSeconds(timestamp).toLocaleString(
{...DateTime.DATETIME_SHORT, ...timeConfig}
);
};
const $lastOutputModal = ref(); // AdminBackupsLastOutputModal
const showLastOutput = () => {
$lastOutputModal.value.show();

View File

@ -34,9 +34,6 @@
<template #cell(name)="row">
{{ row.item.name }} <code>{{ row.item.short_name }}</code>
</template>
<template #cell(auto_assign)="row">
{{ getAutoAssignName(row.item.auto_assign) }}
</template>
<template #cell(actions)="row">
<b-button-group size="sm">
<b-button
@ -92,15 +89,28 @@ const props = defineProps({
const {$gettext} = useTranslate();
const fields = [
{key: 'name', isRowHeader: true, label: $gettext('Field Name'), sortable: false},
{key: 'auto_assign', label: $gettext('Auto-Assign Value'), sortable: false},
{key: 'actions', label: $gettext('Actions'), sortable: false, class: 'shrink'}
{
key: 'name',
isRowHeader: true,
label: $gettext('Field Name'),
sortable: false
},
{
key: 'auto_assign',
label: $gettext('Auto-Assign Value'),
sortable: false,
formatter: (value) => {
return get(props.autoAssignTypes, value, $gettext('None'));
}
},
{
key: 'actions',
label: $gettext('Actions'),
sortable: false,
class: 'shrink'
}
];
const getAutoAssignName = (autoAssign) => {
return get(props.autoAssignTypes, autoAssign, $gettext('None'));
};
const $dataTable = ref(); // DataTable
const relist = () => {

View File

@ -29,12 +29,6 @@
</div>
<code>{{ row.item.short_name }}</code>
</template>
<template #cell(frontend_type)="row">
{{ getFrontendName(row.item.frontend_type) }}
</template>
<template #cell(backend_type)="row">
{{ getBackendName(row.item.backend_type) }}
</template>
<template #cell(actions)="row">
<b-button-group size="sm">
<b-button
@ -117,20 +111,36 @@ const props = defineProps({
const {$gettext} = useTranslate();
const fields = [
{key: 'name', isRowHeader: true, label: $gettext('Name'), sortable: true},
{key: 'frontend_type', label: $gettext('Broadcasting'), sortable: false},
{key: 'backend_type', label: $gettext('AutoDJ'), sortable: false},
{key: 'actions', label: $gettext('Actions'), sortable: false, class: 'shrink'}
{
key: 'name',
isRowHeader: true,
label: $gettext('Name'),
sortable: true
},
{
key: 'frontend_type',
label: $gettext('Broadcasting'),
sortable: false,
formatter: (value) => {
return get(props.frontendTypes, [value, 'name'], '');
}
},
{
key: 'backend_type',
label: $gettext('AutoDJ'),
sortable: false,
formatter: (value) => {
return get(props.backendTypes, [value, 'name'], '');
}
},
{
key: 'actions',
label: $gettext('Actions'),
sortable: false,
class: 'shrink'
}
];
const getFrontendName = (frontend_type) => {
return get(props.frontendTypes, [frontend_type, 'name'], '');
};
const getBackendName = (backend_type) => {
return get(props.backendTypes, [backend_type, 'name'], '');
};
const $datatable = ref(); // Template Ref
const relist = () => {

View File

@ -20,76 +20,90 @@
</div>
</template>
<script>
<script setup>
import mergeExisting from "~/functions/mergeExisting";
import {computed, onMounted, ref, shallowRef} from "vue";
import {useTranslate} from "~/vendor/gettext";
import {useAxios} from "~/vendor/axios";
export default {
name: 'StationsCommonQuota',
props: {
quotaUrl: {
type: String,
required: true
}
},
emits: ['updated'],
data() {
return {
loading: true,
quota: {
used: null,
used_bytes: null,
used_percent: null,
available: null,
available_bytes: null,
quota: null,
quota_bytes: null,
is_full: null,
num_files: null
},
}
},
computed: {
progressVariant() {
if (this.quota.used_percent > 85) {
return 'danger';
} else if (this.quota.used_percent > 65) {
return 'warning';
} else {
return 'default';
}
},
langSpaceUsed() {
const lang = (this.quota.available)
? this.$gettext('%{spaceUsed} of %{spaceTotal} Used')
: this.$gettext('%{spaceUsed} Used');
const langParsed = this.$gettextInterpolate(lang, {
spaceUsed: this.quota.used,
spaceTotal: this.quota.available
});
if (null !== this.quota.num_files) {
const langNumFiles = this.$ngettext('%{filesCount} File', '%{filesCount} Files', this.quota.num_files);
const langNumFilesParsed = this.$gettextInterpolate(langNumFiles, {filesCount: this.quota.num_files});
return langParsed + ' (' + langNumFilesParsed + ')';
}
return langParsed;
},
},
mounted() {
this.update();
},
methods: {
update() {
this.axios.get(this.quotaUrl)
.then((resp) => {
this.quota = mergeExisting(this.quota, resp.data);
this.loading = false;
this.$emit('updated', this.quota);
});
}
const props = defineProps({
quotaUrl: {
type: String,
required: true
}
});
const emit = defineEmits(['updated']);
const loading = ref(true);
const quota = shallowRef({
used: null,
used_bytes: null,
used_percent: null,
available: null,
available_bytes: null,
quota: null,
quota_bytes: null,
is_full: null,
num_files: null
});
const progressVariant = computed(() => {
if (quota.value.used_percent > 85) {
return 'danger';
} else if (quota.value.used_percent > 65) {
return 'warning';
} else {
return 'default';
}
});
const {$gettext, $ngettext} = useTranslate();
const langSpaceUsed = computed(() => {
let langSpaceUsed;
if (quota.value.available) {
langSpaceUsed = $gettext(
'%{spaceUsed} of %{spaceTotal} Used',
{
spaceUsed: quota.value.used,
spaceTotal: quota.value.available
}
);
} else {
langSpaceUsed = $gettext(
'%{spaceUsed} Used',
{
spaceUsed: quota.value.used,
}
)
}
if (null !== quota.value.num_files) {
const langNumFiles = $ngettext(
'%{filesCount} File',
'%{filesCount} Files',
quota.value.num_files,
{filesCount: quota.value.num_files}
);
return langSpaceUsed + ' (' + langNumFiles + ')';
}
return langSpaceUsed;
});
const {axios} = useAxios();
const update = () => {
axios.get(props.quotaUrl).then((resp) => {
quota.value = mergeExisting(quota.value, resp.data);
loading.value = false;
emit('updated', quota.value);
});
}
onMounted(update);
</script>

View File

@ -9,55 +9,42 @@
/>
</template>
<script>
<script setup>
import FlowUpload from '~/components/Common/FlowUpload';
export default {
name: 'FileUpload',
components: {FlowUpload},
props: {
uploadUrl: {
type: String,
required: true
},
currentDirectory: {
type: String,
required: true
},
searchPhrase: {
type: String,
required: true
},
validMimeTypes: {
type: Array,
default() {
return ['audio/*'];
}
}
const props = defineProps({
uploadUrl: {
type: String,
required: true
},
emits: ['relist'],
data() {
return {
flow: null,
files: []
};
currentDirectory: {
type: String,
required: true
},
computed: {
flowConfiguration() {
return {
query: () => {
return {
'currentDirectory': this.currentDirectory,
'searchPhrase': this.searchPhrase
};
}
};
}
searchPhrase: {
type: String,
required: true
},
methods: {
onFlowUpload() {
this.$emit('relist');
validMimeTypes: {
type: Array,
default() {
return ['audio/*'];
}
}
});
const emit = defineEmits(['relist']);
const flowConfiguration = {
query: () => {
return {
'currentDirectory': props.currentDirectory,
'searchPhrase': props.searchPhrase
};
}
};
const onFlowUpload = () => {
emit('relist');
}
</script>

View File

@ -1,7 +1,7 @@
<template>
<b-modal
id="create_directory"
ref="modal"
ref="$modal"
centered
:title="$gettext('New Directory')"
>
@ -32,62 +32,63 @@
</template>
</b-modal>
</template>
<script>
import useVuelidate from "@vuelidate/core";
<script setup>
import {required} from '@vuelidate/validators';
import BWrappedFormGroup from "~/components/Form/BWrappedFormGroup";
import {useVuelidateOnForm} from "~/functions/useVuelidateOnForm";
import {ref} from "vue";
import {useNotify} from "~/vendor/bootstrapVue";
import {useAxios} from "~/vendor/axios";
import {useTranslate} from "~/vendor/gettext";
export default {
name: 'NewDirectoryModal',
components: {BWrappedFormGroup},
props: {
currentDirectory: {
type: String,
required: true
},
mkdirUrl: {
type: String,
required: true
}
const props = defineProps({
currentDirectory: {
type: String,
required: true
},
emits: ['relist'],
setup() {
return {v$: useVuelidate()}
},
data() {
return {
newDirectory: null
};
},
validations: {
newDirectory: {
required
}
},
methods: {
close() {
this.newDirectory = null;
this.v$.$reset();
this.$refs.modal.hide();
},
doMkdir() {
this.v$.$touch();
if (this.v$.$errors.length > 0) {
return;
}
this.$wrapWithLoading(
this.axios.post(this.mkdirUrl, {
'currentDirectory': this.currentDirectory,
'name': this.newDirectory
})
).then(() => {
this.$notifySuccess(this.$gettext('New directory created.'));
}).finally(() => {
this.$emit('relist');
this.close();
});
}
mkdirUrl: {
type: String,
required: true
}
});
const emit = defineEmits(['relist']);
const {form, v$, resetForm, ifValid} = useVuelidateOnForm(
{
newDirectory: {required}
},
{
newDirectory: null
}
);
const $modal = ref(); // Template Ref
const close = () => {
resetForm();
$modal.value.hide();
};
const {wrapWithLoading, notifySuccess} = useNotify();
const {axios} = useAxios();
const {$gettext} = useTranslate();
const doMkdir = () => {
ifValid(() => {
wrapWithLoading(
axios.post(props.mkdirUrl, {
'currentDirectory': props.currentDirectory,
'name': form.value.newDirectory
})
).then(() => {
notifySuccess($gettext('New directory created.'));
}).finally(() => {
emit('relist');
close();
});
});
};
</script>

View File

@ -1,7 +1,7 @@
<template>
<b-modal
id="rename_file"
ref="modal"
ref="$modal"
centered
:title="$gettext('Rename File/Directory')"
>
@ -32,63 +32,69 @@
</template>
</b-modal>
</template>
<script>
import useVuelidate from "@vuelidate/core";
<script setup>
import {required} from '@vuelidate/validators';
import BWrappedFormGroup from "~/components/Form/BWrappedFormGroup";
import {ref} from "vue";
import {useVuelidateOnForm} from "~/functions/useVuelidateOnForm";
import {useNotify} from "~/vendor/bootstrapVue";
import {useAxios} from "~/vendor/axios";
export default {
name: 'RenameModal',
components: {BWrappedFormGroup},
props: {
renameUrl: {
type: String,
required: true
}
},
emits: ['relist'],
setup() {
return {v$: useVuelidate()}
},
data() {
return {
form: {
file: null,
newPath: null
}
};
},
validations: {
form: {
newPath: {
required
}
}
},
methods: {
open(filePath) {
this.form.file = filePath;
this.form.newPath = filePath;
this.$refs.modal.show();
},
close() {
this.v$.$reset();
this.$refs.modal.hide();
},
doRename() {
this.v$.$touch();
if (this.v$.$errors.length > 0) {
return;
}
this.$wrapWithLoading(
this.axios.put(this.renameUrl, this.form)
).finally(() => {
this.$refs.modal.hide();
this.$emit('relist');
});
}
const props = defineProps({
renameUrl: {
type: String,
required: true
}
});
const emit = defineEmits(['relist']);
const file = ref(null);
const {form, v$, resetForm, ifValid} = useVuelidateOnForm(
{
newPath: {required}
},
{
newPath: null
}
);
const $modal = ref(); // Template Ref
const open = (filePath) => {
file.value = filePath;
form.value.newPath = filePath;
$modal.value.show();
};
const close = () => {
resetForm();
file.value = null;
$modal.value.hide();
};
const {wrapWithLoading} = useNotify();
const {axios} = useAxios();
const doRename = () => {
ifValid(() => {
wrapWithLoading(
axios.put(props.renameUrl, {
file: file.value,
...form.value
})
).finally(() => {
$modal.value.hide();
emit('relist');
});
});
};
defineExpose({
open
});
</script>

View File

@ -44,27 +44,23 @@
</b-tab>
</template>
<script>
<script setup>
import {FRONTEND_ICECAST} from '~/components/Entity/RadioAdapters';
import BWrappedFormGroup from "~/components/Form/BWrappedFormGroup";
import {computed} from "vue";
export default {
name: 'MountFormAdvanced',
components: {BWrappedFormGroup},
props: {
form: {
type: Object,
required: true
},
stationFrontendType: {
type: String,
required: true
}
const props = defineProps({
form: {
type: Object,
required: true
},
computed: {
isIcecast() {
return FRONTEND_ICECAST === this.stationFrontendType;
}
stationFrontendType: {
type: String,
required: true
}
};
});
const isIcecast = computed(() => {
return FRONTEND_ICECAST === props.stationFrontendType;
});
</script>

View File

@ -62,72 +62,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";
export default {
name: 'MountFormAutoDj',
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

@ -147,37 +147,36 @@
</b-tab>
</template>
<script>
<script setup>
import {FRONTEND_ICECAST, FRONTEND_SHOUTCAST} from '~/components/Entity/RadioAdapters';
import BWrappedFormGroup from "~/components/Form/BWrappedFormGroup";
import BWrappedFormCheckbox from "~/components/Form/BWrappedFormCheckbox";
import {useTranslate} from "~/vendor/gettext";
import {computed} from "vue";
export default {
name: 'MountFormBasicInfo',
components: {BWrappedFormCheckbox, BWrappedFormGroup},
props: {
form: {
type: Object,
required: true
},
stationFrontendType: {
type: String,
required: true
}
const props = defineProps({
form: {
type: Object,
required: true
},
computed: {
langAuthhashDesc() {
return this.$gettext(
'If your stream is set to advertise to YP directories above, you must specify an authorization hash. You can manage authhashes <a href="%{ url }" target="_blank">on the Shoutcast web site</a>.',
{url: 'https://radiomanager.shoutcast.com/'}
);
},
isIcecast () {
return FRONTEND_ICECAST === this.stationFrontendType;
},
isShoutcast () {
return FRONTEND_SHOUTCAST === this.stationFrontendType;
}
stationFrontendType: {
type: String,
required: true
}
};
});
const {$gettext} = useTranslate();
const langAuthhashDesc = $gettext(
'If your stream is set to advertise to YP directories above, you must specify an authorization hash. You can manage authhashes <a href="%{ url }" target="_blank">on the Shoutcast web site</a>.',
{url: 'https://radiomanager.shoutcast.com/'}
);
const isIcecast = computed(() => {
return FRONTEND_ICECAST === props.stationFrontendType;
});
const isShoutcast = computed(() => {
return FRONTEND_SHOUTCAST === props.stationFrontendType;
});
</script>

View File

@ -1,9 +1,8 @@
<template>
<modal-form
id="clone_modal"
ref="modal"
ref="$modal"
:title="$gettext('Duplicate Playlist')"
:error="error"
:disable-save-button="v$.form.$invalid"
@submit="doSubmit"
@hidden="clearContents"
@ -46,80 +45,73 @@
</modal-form>
</template>
<script>
import useVuelidate from "@vuelidate/core";
<script setup>
import {required} from '@vuelidate/validators';
import BWrappedFormGroup from "~/components/Form/BWrappedFormGroup";
import ModalForm from "~/components/Common/ModalForm";
import {useVuelidateOnForm} from "~/functions/useVuelidateOnForm";
import {ref} from "vue";
import {useTranslate} from "~/vendor/gettext";
import {useNotify} from "~/vendor/bootstrapVue";
import {useAxios} from "~/vendor/axios";
export default {
name: 'CloneModal',
components: {ModalForm, BWrappedFormGroup},
emits: ['relist', 'needs-restart'],
setup() {
return {v$: useVuelidate()}
const emit = defineEmits(['relist', 'needs-restart']);
const cloneUrl = ref(null);
const {form, v$, resetForm, ifValid} = useVuelidateOnForm(
{
'name': {required},
'clone': {}
},
data() {
return {
error: null,
cloneUrl: null,
form: {}
};
},
validations: {
form: {
'name': { required },
'clone': {}
}
},
methods: {
resetForm () {
this.form = {
'name': '',
'clone': []
};
},
open (name, cloneUrl) {
this.error = null;
this.resetForm();
this.cloneUrl = cloneUrl;
this.form.name = this.$gettext(
'%{name} - Copy',
{name: name}
);
this.$refs.modal.show();
},
async doSubmit() {
this.v$.$touch();
if (this.v$.$errors.length > 0) {
return;
}
this.error = null;
this.$wrapWithLoading(
this.axios({
method: 'POST',
url: this.cloneUrl,
data: this.form
})
).then(() => {
this.$notifySuccess();
this.$emit('needs-restart');
this.$emit('relist');
this.$refs.modal.hide();
});
},
clearContents() {
this.error = null;
this.cloneUrl = null;
this.resetForm();
this.v$.$reset();
}
{
'name': '',
'clone': []
}
);
const clearContents = () => {
cloneUrl.value = null;
resetForm();
};
const {$gettext} = useTranslate();
const $modal = ref(); // Template Ref
const open = (name, newCloneUrl) => {
clearContents();
cloneUrl.value = newCloneUrl;
form.value.name = $gettext(
'%{name} - Copy',
{name: name}
);
$modal.value.show();
};
const {wrapWithLoading, notifySuccess} = useNotify();
const {axios} = useAxios();
const doSubmit = () => {
ifValid(() => {
wrapWithLoading(
axios({
method: 'POST',
url: cloneUrl.value,
data: form.value
})
).then(() => {
notifySuccess();
emit('needs-restart');
emit('relist');
$modal.value.hide();
});
});
};
defineExpose({
open
});
</script>

View File

@ -419,35 +419,26 @@
</b-tab>
</template>
<script>
<script setup>
import BWrappedFormGroup from "~/components/Form/BWrappedFormGroup";
import BWrappedFormCheckbox from "~/components/Form/BWrappedFormCheckbox";
import BFormFieldset from "~/components/Form/BFormFieldset";
import {map, range} from "lodash";
export default {
name: 'PlaylistEditBasicInfo',
components: {BFormFieldset, BWrappedFormCheckbox, BWrappedFormGroup},
props: {
form: {
type: Object,
required: true
}
},
data() {
let weightOptions = [
{value: 1, text: '1 - ' + this.$gettext('Low')},
{value: 2, text: '2'},
{value: 3, text: '3 - ' + this.$gettext('Default')},
{value: 4, text: '4'},
{value: 5, text: '5 - ' + this.$gettext('High')}
];
for (let i = 6; i <= 25; i++) {
weightOptions.push({value: i, text: i});
}
return {
weightOptions: weightOptions
};
const props = defineProps({
form: {
type: Object,
required: true
}
};
});
const weightOptions = map(
range(1, 26),
(val) => {
return {
value: val,
text: val
}
}
);
</script>

View File

@ -1,7 +1,7 @@
<template>
<b-modal
id="import_modal"
ref="modal"
ref="$modal"
:title="$gettext('Import from PLS/M3U')"
@hidden="onHidden"
>
@ -91,51 +91,58 @@
</b-modal>
</template>
<script>
<script setup>
import InvisibleSubmitButton from '~/components/Common/InvisibleSubmitButton';
import {ref} from "vue";
import {useNotify} from "~/vendor/bootstrapVue";
import {useAxios} from "~/vendor/axios";
export default {
name: 'PlaylistImportModal',
components: {InvisibleSubmitButton},
emits: ['relist'],
data() {
return {
importPlaylistUrl: null,
playlistFile: null,
results: null,
};
},
methods: {
open(importPlaylistUrl) {
this.playlistFile = null;
this.importPlaylistUrl = importPlaylistUrl;
const emit = defineEmits(['relist']);
this.$refs.modal.show();
},
doSubmit () {
let formData = new FormData();
formData.append('playlist_file', this.playlistFile);
const importPlaylistUrl = ref(null);
const playlistFile = ref(null);
const results = ref(null);
this.$wrapWithLoading(
this.axios.post(this.importPlaylistUrl, formData)
).then((resp) => {
if (resp.data.success) {
this.results = resp.data;
const $modal = ref(); // Template Ref
this.$notifySuccess(resp.data.message);
} else {
this.$notifyError(resp.data.message);
this.close();
}
});
},
close () {
this.$refs.modal.hide();
},
onHidden () {
this.$emit('relist');
this.results = null;
}
}
const open = (newImportPlaylistUrl) => {
playlistFile.value = null;
importPlaylistUrl.value = newImportPlaylistUrl;
$modal.value.show();
};
const {wrapWithLoading, notifySuccess, notifyError} = useNotify();
const {axios} = useAxios();
const doSubmit = () => {
let formData = new FormData();
formData.append('playlist_file', playlistFile.value);
wrapWithLoading(
axios.post(importPlaylistUrl.value, formData)
).then((resp) => {
if (resp.data.success) {
results.value = resp.data;
notifySuccess(resp.data.message);
} else {
notifyError(resp.data.message);
close();
}
});
};
const close = () => {
$modal.value.hide();
};
const onHidden = () => {
emit('relist');
results.value = null;
};
defineExpose({
open
});
</script>

View File

@ -1,7 +1,7 @@
<template>
<b-modal
id="queue_modal"
ref="modal"
ref="$modal"
size="lg"
:title="$gettext('Playback Queue')"
:busy="loading"
@ -62,43 +62,52 @@
</b-modal>
</template>
<script>
<script setup>
import {ref} from "vue";
import {useAxios} from "~/vendor/axios";
import {useNotify} from "~/vendor/bootstrapVue";
import {useTranslate} from "~/vendor/gettext";
export default {
name: 'QueueModal',
data () {
return {
loading: true,
queueUrl: null,
media: []
};
},
methods: {
open (queueUrl) {
this.$refs.modal.show();
this.queueUrl = queueUrl;
this.loading = true;
const loading = ref(true);
const queueUrl = ref(null);
const media = ref([]);
this.axios.get(this.queueUrl).then((resp) => {
this.media = resp.data;
this.loading = false;
});
},
doClear () {
this.$wrapWithLoading(
this.axios.delete(this.queueUrl)
).then(() => {
this.$notifySuccess(this.$gettext('Playlist queue cleared.'));
this.close();
});
},
close () {
this.loading = false;
this.error = null;
this.queueUrl = null;
const $modal = ref(); // Template Ref
this.$refs.modal.hide();
}
}
const {axios} = useAxios();
const open = (newQueueUrl) => {
queueUrl.value = newQueueUrl;
loading.value = true;
axios.get(newQueueUrl).then((resp) => {
media.value = resp.data;
loading.value = false;
});
$modal.value.show();
};
const close = () => {
loading.value = false;
queueUrl.value = null;
$modal.value.hide();
}
const {wrapWithLoading, notifySuccess} = useNotify();
const {$gettext} = useTranslate();
const doClear = () => {
wrapWithLoading(
axios.delete(queueUrl.value)
).then(() => {
notifySuccess($gettext('Playlist queue cleared.'));
close();
});
};
defineExpose({
open
});
</script>

View File

@ -18,9 +18,3 @@
</div>
</section>
</template>
<script>
export default {
inheritAttrs: false,
}
</script>

View File

@ -92,12 +92,6 @@
</b-modal>
</template>
<script>
export default {
inheritAttrs: false
}
</script>
<script setup>
import CopyToClipboardButton from '~/components/Common/CopyToClipboardButton';
import {computed, ref} from "vue";

View File

@ -48,12 +48,6 @@
</div>
</template>
<script>
export default {
inheritAttrs: false
};
</script>
<script setup>
import {DateTime} from "luxon";
import {map} from "lodash";

View File

@ -167,12 +167,6 @@
</section>
</template>
<script>
export default {
inheritAttrs: false
};
</script>
<script setup>
import Icon from '~/components/Common/Icon';
import PlayButton from "~/components/Common/PlayButton";