Make Webhook Edit Modal Composition API.
This commit is contained in:
parent
6a85fab94c
commit
469c89e0f6
|
@ -12,7 +12,7 @@
|
|||
content-class="mt-3"
|
||||
pills
|
||||
>
|
||||
<form-basic-info :form="v$"/>
|
||||
<form-basic-info :form="v$" />
|
||||
</b-tabs>
|
||||
</modal-form>
|
||||
</template>
|
||||
|
@ -40,7 +40,6 @@ const {
|
|||
loading,
|
||||
error,
|
||||
isEditMode,
|
||||
form,
|
||||
v$,
|
||||
clearContents,
|
||||
create,
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<template>
|
||||
<modal-form
|
||||
ref="modal"
|
||||
ref="$modal"
|
||||
:loading="loading"
|
||||
:title="langTitle"
|
||||
:error="error"
|
||||
:disable-save-button="v$.form.$invalid"
|
||||
:disable-save-button="v$.$invalid"
|
||||
@submit="doSubmit"
|
||||
@hidden="clearContents"
|
||||
>
|
||||
|
@ -13,152 +13,165 @@
|
|||
pills
|
||||
>
|
||||
<mount-form-basic-info
|
||||
:form="v$.form"
|
||||
:form="v$"
|
||||
:station-frontend-type="stationFrontendType"
|
||||
/>
|
||||
<mount-form-auto-dj
|
||||
:form="v$.form"
|
||||
:form="v$"
|
||||
:station-frontend-type="stationFrontendType"
|
||||
/>
|
||||
<mount-form-intro
|
||||
v-model="v$.form.intro_file.$model"
|
||||
v-model="v$.intro_file.$model"
|
||||
:record-has-intro="record.intro_path !== null"
|
||||
:new-intro-url="newIntroUrl"
|
||||
:edit-intro-url="record.links.intro"
|
||||
/>
|
||||
<mount-form-advanced
|
||||
v-if="showAdvanced"
|
||||
:form="v$.form"
|
||||
:form="v$"
|
||||
:station-frontend-type="stationFrontendType"
|
||||
/>
|
||||
</b-tabs>
|
||||
</modal-form>
|
||||
</template>
|
||||
<script>
|
||||
import {required} from '@vuelidate/validators';
|
||||
import BaseEditModal from '~/components/Common/BaseEditModal';
|
||||
|
||||
<script setup>
|
||||
import {required} from '@vuelidate/validators';
|
||||
import {FRONTEND_ICECAST, FRONTEND_SHOUTCAST} from '~/components/Entity/RadioAdapters';
|
||||
import MountFormBasicInfo from './Form/BasicInfo';
|
||||
import MountFormAutoDj from './Form/AutoDj';
|
||||
import MountFormAdvanced from './Form/Advanced';
|
||||
import MountFormIntro from "./Form/Intro";
|
||||
import mergeExisting from "~/functions/mergeExisting";
|
||||
import useVuelidate from "@vuelidate/core";
|
||||
import {baseEditModalProps, useBaseEditModal} from "~/functions/useBaseEditModal";
|
||||
import {computed, ref} from "vue";
|
||||
import {useNotify} from "~/vendor/bootstrapVue";
|
||||
import {useTranslate} from "~/vendor/gettext";
|
||||
import {useResettableRef} from "~/functions/useResettableRef";
|
||||
import ModalForm from "~/components/Common/ModalForm.vue";
|
||||
|
||||
/* TODO Options API */
|
||||
const props = defineProps({
|
||||
...baseEditModalProps,
|
||||
stationFrontendType: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
newIntroUrl: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
showAdvanced: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
});
|
||||
|
||||
export default {
|
||||
name: 'EditModal',
|
||||
components: {MountFormIntro, MountFormAdvanced, MountFormAutoDj, MountFormBasicInfo},
|
||||
mixins: [BaseEditModal],
|
||||
props: {
|
||||
stationFrontendType: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
newIntroUrl: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
showAdvanced: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
},
|
||||
emits: ['relist', 'needs-restart'],
|
||||
setup() {
|
||||
return {v$: useVuelidate()}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
record: {
|
||||
intro_path: null,
|
||||
links: {
|
||||
intro: null
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
validations() {
|
||||
const emit = defineEmits(['relist', 'needs-restart']);
|
||||
|
||||
const $modal = ref(); // Template Ref
|
||||
|
||||
const {notifySuccess} = useNotify();
|
||||
|
||||
const {record, reset} = useResettableRef({
|
||||
intro_path: null,
|
||||
links: {
|
||||
intro: null
|
||||
}
|
||||
});
|
||||
|
||||
const {
|
||||
loading,
|
||||
error,
|
||||
isEditMode,
|
||||
v$,
|
||||
clearContents,
|
||||
create,
|
||||
edit,
|
||||
doSubmit,
|
||||
close
|
||||
} = useBaseEditModal(
|
||||
props,
|
||||
emit,
|
||||
$modal,
|
||||
() => computed(() => {
|
||||
let validations = {
|
||||
form: {
|
||||
name: {required},
|
||||
display_name: {},
|
||||
is_visible_on_public_pages: {},
|
||||
is_default: {},
|
||||
relay_url: {},
|
||||
is_public: {},
|
||||
enable_autodj: {},
|
||||
autodj_format: {},
|
||||
autodj_bitrate: {},
|
||||
max_listener_duration: {required},
|
||||
intro_file: {}
|
||||
}
|
||||
name: {required},
|
||||
display_name: {},
|
||||
is_visible_on_public_pages: {},
|
||||
is_default: {},
|
||||
relay_url: {},
|
||||
is_public: {},
|
||||
enable_autodj: {},
|
||||
autodj_format: {},
|
||||
autodj_bitrate: {},
|
||||
max_listener_duration: {required},
|
||||
intro_file: {}
|
||||
};
|
||||
|
||||
if (this.showAdvanced) {
|
||||
validations.form.custom_listen_url = {};
|
||||
if (props.showAdvanced) {
|
||||
validations.custom_listen_url = {};
|
||||
}
|
||||
|
||||
if (FRONTEND_SHOUTCAST === this.stationFrontendType) {
|
||||
validations.form.authhash = {};
|
||||
if (FRONTEND_SHOUTCAST === props.stationFrontendType) {
|
||||
validations.authhash = {};
|
||||
}
|
||||
if (FRONTEND_ICECAST === this.stationFrontendType) {
|
||||
validations.form.fallback_mount = {};
|
||||
|
||||
if (this.showAdvanced) {
|
||||
validations.form.frontend_config = {};
|
||||
if (FRONTEND_ICECAST === props.stationFrontendType) {
|
||||
validations.fallback_mount = {};
|
||||
|
||||
if (props.showAdvanced) {
|
||||
validations.frontend_config = {};
|
||||
}
|
||||
}
|
||||
|
||||
return validations;
|
||||
}),
|
||||
{
|
||||
name: null,
|
||||
display_name: null,
|
||||
is_visible_on_public_pages: true,
|
||||
is_default: false,
|
||||
relay_url: null,
|
||||
is_public: true,
|
||||
enable_autodj: true,
|
||||
autodj_format: 'mp3',
|
||||
autodj_bitrate: 128,
|
||||
custom_listen_url: null,
|
||||
authhash: null,
|
||||
fallback_mount: '/error.mp3',
|
||||
max_listener_duration: 0,
|
||||
frontend_config: null,
|
||||
intro_file: null
|
||||
},
|
||||
computed: {
|
||||
langTitle () {
|
||||
return this.isEditMode
|
||||
? this.$gettext('Edit Mount Point')
|
||||
: this.$gettext('Add Mount Point');
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetForm () {
|
||||
this.record = {
|
||||
intro_path: null,
|
||||
links: {
|
||||
intro: null
|
||||
}
|
||||
};
|
||||
this.form = {
|
||||
name: null,
|
||||
display_name: null,
|
||||
is_visible_on_public_pages: true,
|
||||
is_default: false,
|
||||
relay_url: null,
|
||||
is_public: true,
|
||||
enable_autodj: true,
|
||||
autodj_format: 'mp3',
|
||||
autodj_bitrate: 128,
|
||||
custom_listen_url: null,
|
||||
authhash: null,
|
||||
fallback_mount: '/error.mp3',
|
||||
max_listener_duration: 0,
|
||||
frontend_config: null,
|
||||
intro_file: null
|
||||
};
|
||||
{
|
||||
resetForm: (originalResetForm) => {
|
||||
originalResetForm();
|
||||
reset();
|
||||
},
|
||||
populateForm(d) {
|
||||
this.record = d;
|
||||
this.form = mergeExisting(this.form, d);
|
||||
populateForm: (data, formRef) => {
|
||||
record.value = data;
|
||||
formRef.value = mergeExisting(formRef.value, data);
|
||||
},
|
||||
onSubmitSuccess() {
|
||||
this.$notifySuccess();
|
||||
|
||||
this.$emit('needs-restart');
|
||||
this.$emit('relist');
|
||||
|
||||
this.close();
|
||||
onSubmitSuccess: () => {
|
||||
notifySuccess();
|
||||
emit('relist');
|
||||
emit('needs-restart');
|
||||
close();
|
||||
},
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
const {$gettext} = useTranslate();
|
||||
|
||||
const langTitle = computed(() => {
|
||||
return isEditMode.value
|
||||
? $gettext('Edit Mount Point')
|
||||
: $gettext('Add Mount Point');
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
create,
|
||||
edit,
|
||||
close
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<template>
|
||||
<modal-form
|
||||
ref="modal"
|
||||
ref="$modal"
|
||||
:loading="loading"
|
||||
:title="langTitle"
|
||||
:error="error"
|
||||
:disable-save-button="v$.form.$invalid"
|
||||
:disable-save-button="v$.$invalid"
|
||||
@submit="doSubmit"
|
||||
@hidden="clearContents"
|
||||
>
|
||||
|
@ -26,22 +26,22 @@
|
|||
|
||||
<basic-info
|
||||
:trigger-options="triggerOptions"
|
||||
:form="v$.form"
|
||||
:form="v$"
|
||||
/>
|
||||
</b-tab>
|
||||
<b-tab :title="typeTitle">
|
||||
<component
|
||||
:is="formComponent"
|
||||
:now-playing-url="nowPlayingUrl"
|
||||
:form="v$.form"
|
||||
:form="v$"
|
||||
/>
|
||||
</b-tab>
|
||||
</b-tabs>
|
||||
</modal-form>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
<script setup>
|
||||
import {required} from '@vuelidate/validators';
|
||||
import BaseEditModal from '~/components/Common/BaseEditModal';
|
||||
import TypeSelect from "./Form/TypeSelect";
|
||||
import BasicInfo from "./Form/BasicInfo";
|
||||
import {get, map} from "lodash";
|
||||
|
@ -54,356 +54,385 @@ import Twitter from "./Form/Twitter";
|
|||
import GoogleAnalytics from "./Form/GoogleAnalytics";
|
||||
import MatomoAnalytics from "./Form/MatomoAnalytics";
|
||||
import Mastodon from "./Form/Mastodon";
|
||||
import useVuelidate from "@vuelidate/core";
|
||||
import {baseEditModalProps, useBaseEditModal} from "~/functions/useBaseEditModal";
|
||||
import {computed, ref} from "vue";
|
||||
import {useTranslate} from "~/vendor/gettext";
|
||||
import ModalForm from "~/components/Common/ModalForm.vue";
|
||||
|
||||
/* TODO Options API */
|
||||
const props = defineProps({
|
||||
...baseEditModalProps,
|
||||
nowPlayingUrl: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
webhookTypes: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
triggerTitles: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
triggerDescriptions: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
|
||||
export default {
|
||||
name: 'EditModal',
|
||||
components: {BasicInfo, TypeSelect},
|
||||
mixins: [BaseEditModal],
|
||||
props: {
|
||||
nowPlayingUrl: {
|
||||
type: String,
|
||||
required: true
|
||||
const emit = defineEmits(['relist']);
|
||||
|
||||
const type = ref(null);
|
||||
|
||||
const $modal = ref(); // Template Ref
|
||||
|
||||
const {$gettext} = useTranslate();
|
||||
|
||||
const langPoweredByAzuraCast = $gettext('Powered by AzuraCast');
|
||||
|
||||
const langDiscordDefaultContent = $gettext(
|
||||
'Now playing on %{ station }:',
|
||||
{'station': '{{ station.name }}'}
|
||||
);
|
||||
|
||||
const langTelegramDefaultContent = $gettext(
|
||||
'Now playing on %{ station }: %{ title } by %{ artist }! Tune in now.',
|
||||
{
|
||||
station: '{{ station.name }}',
|
||||
title: '{{ now_playing.song.title }}',
|
||||
artist: '{{ now_playing.song.artist }}'
|
||||
}
|
||||
);
|
||||
|
||||
const langTwitterDefaultMessage = $gettext(
|
||||
'Now playing on %{ station }: %{ title } by %{ artist }! Tune in now: %{ url }',
|
||||
{
|
||||
station: '{{ station.name }}',
|
||||
title: '{{ now_playing.song.title }}',
|
||||
artist: '{{ now_playing.song.artist }}',
|
||||
url: '{{ station.public_player_url }}'
|
||||
}
|
||||
);
|
||||
|
||||
const langTwitterSongChangedLiveMessage = $gettext(
|
||||
'Now playing on %{ station }: %{ title } by %{ artist } with your host, %{ dj }! Tune in now: %{ url }',
|
||||
{
|
||||
station: '{{ station.name }}',
|
||||
title: '{{ now_playing.song.title }}',
|
||||
artist: '{{ now_playing.song.artist }}',
|
||||
dj: '{{ live.streamer_name }}',
|
||||
url: '{{ station.public_player_url }}'
|
||||
}
|
||||
);
|
||||
|
||||
const langTwitterDjOnMessage = $gettext(
|
||||
'%{ dj } is now live on %{ station }! Tune in now: %{ url }',
|
||||
{
|
||||
dj: '{{ live.streamer_name }}',
|
||||
station: '{{ station.name }}',
|
||||
url: '{{ station.public_player_url }}'
|
||||
}
|
||||
);
|
||||
|
||||
const langTwitterDjOffMessage = $gettext(
|
||||
'Thanks for listening to %{ station }!',
|
||||
{
|
||||
station: '{{ station.name }}',
|
||||
}
|
||||
);
|
||||
|
||||
const langTwitterStationOfflineMessage = $gettext(
|
||||
'%{ station } is going offline for now.',
|
||||
{
|
||||
station: '{{ station.name }}'
|
||||
}
|
||||
);
|
||||
|
||||
const langTwitterStationOnlineMessage = $gettext(
|
||||
'%{ station } is back online! Tune in now: %{ url }',
|
||||
{
|
||||
station: '{{ station.name }}',
|
||||
url: '{{ station.public_player_url }}'
|
||||
}
|
||||
);
|
||||
|
||||
const webhookConfig = {
|
||||
'generic': {
|
||||
component: Generic,
|
||||
validations: {
|
||||
webhook_url: {required},
|
||||
basic_auth_username: {},
|
||||
basic_auth_password: {},
|
||||
timeout: {},
|
||||
},
|
||||
webhookTypes: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
triggerTitles: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
triggerDescriptions: {
|
||||
type: Object,
|
||||
required: true
|
||||
defaultConfig: {
|
||||
webhook_url: '',
|
||||
basic_auth_username: '',
|
||||
basic_auth_password: '',
|
||||
timeout: '5',
|
||||
}
|
||||
},
|
||||
setup() {
|
||||
return {v$: useVuelidate()}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
type: null,
|
||||
'email': {
|
||||
component: Email,
|
||||
validations: {
|
||||
to: {required},
|
||||
subject: {required},
|
||||
message: {required}
|
||||
},
|
||||
defaultConfig: {
|
||||
to: '',
|
||||
subject: '',
|
||||
message: ''
|
||||
}
|
||||
},
|
||||
validations() {
|
||||
let validations = {
|
||||
type: {required},
|
||||
form: {
|
||||
name: {required},
|
||||
triggers: {},
|
||||
config: {}
|
||||
}
|
||||
};
|
||||
|
||||
if (this.triggerOptions.length > 0) {
|
||||
validations.form.triggers = {required};
|
||||
}
|
||||
|
||||
if (this.type !== null) {
|
||||
validations.form.config = get(this.webhookConfig, [this.type, 'validations'], {});
|
||||
}
|
||||
|
||||
return validations;
|
||||
},
|
||||
computed: {
|
||||
langTitle() {
|
||||
return this.isEditMode
|
||||
? this.$gettext('Edit Web Hook')
|
||||
: this.$gettext('Add Web Hook');
|
||||
'tunein': {
|
||||
component: Tunein,
|
||||
validations: {
|
||||
station_id: {required},
|
||||
partner_id: {required},
|
||||
partner_key: {required},
|
||||
},
|
||||
triggerOptions() {
|
||||
if (!this.type) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let webhookKeys = get(this.webhookTypes, [this.type, 'triggers'], []);
|
||||
return map(webhookKeys, (key) => {
|
||||
return {
|
||||
html:
|
||||
'<h6 class="font-weight-bold mb-0">' + this.triggerTitles[key] + '</h6>'
|
||||
+ '<p class="card-text small">' + this.triggerDescriptions[key] + '</p>',
|
||||
value: key
|
||||
};
|
||||
});
|
||||
},
|
||||
typeTitle() {
|
||||
return get(this.webhookTypes, [this.type, 'name'], '');
|
||||
},
|
||||
formComponent() {
|
||||
return get(this.webhookConfig, [this.type, 'component'], Generic);
|
||||
},
|
||||
webhookConfig() {
|
||||
return {
|
||||
'generic': {
|
||||
component: Generic,
|
||||
validations: {
|
||||
webhook_url: {required},
|
||||
basic_auth_username: {},
|
||||
basic_auth_password: {},
|
||||
timeout: {},
|
||||
},
|
||||
defaultConfig: {
|
||||
webhook_url: '',
|
||||
basic_auth_username: '',
|
||||
basic_auth_password: '',
|
||||
timeout: '5',
|
||||
}
|
||||
},
|
||||
'email': {
|
||||
component: Email,
|
||||
validations: {
|
||||
to: {required},
|
||||
subject: {required},
|
||||
message: {required}
|
||||
},
|
||||
defaultConfig: {
|
||||
to: '',
|
||||
subject: '',
|
||||
message: ''
|
||||
}
|
||||
},
|
||||
'tunein': {
|
||||
component: Tunein,
|
||||
validations: {
|
||||
station_id: {required},
|
||||
partner_id: {required},
|
||||
partner_key: {required},
|
||||
},
|
||||
defaultConfig: {
|
||||
station_id: '',
|
||||
partner_id: '',
|
||||
partner_key: ''
|
||||
}
|
||||
},
|
||||
'discord': {
|
||||
component: Discord,
|
||||
validations: {
|
||||
webhook_url: {required},
|
||||
content: {},
|
||||
title: {},
|
||||
description: {},
|
||||
url: {},
|
||||
author: {},
|
||||
thumbnail: {},
|
||||
footer: {},
|
||||
},
|
||||
defaultConfig: {
|
||||
webhook_url: '',
|
||||
content: this.langDiscordDefaultContent,
|
||||
title: '{{ now_playing.song.title }}',
|
||||
description: '{{ now_playing.song.artist }}',
|
||||
url: '{{ station.listen_url }}',
|
||||
author: '{{ live.streamer_name }}',
|
||||
thumbnail: '{{ now_playing.song.art }}',
|
||||
footer: this.langPoweredByAzuraCast,
|
||||
}
|
||||
},
|
||||
'telegram': {
|
||||
component: Telegram,
|
||||
validations: {
|
||||
bot_token: {required},
|
||||
chat_id: {required},
|
||||
api: {},
|
||||
text: {required},
|
||||
parse_mode: {required}
|
||||
},
|
||||
defaultConfig: {
|
||||
bot_token: '',
|
||||
chat_id: '',
|
||||
api: '',
|
||||
text: this.langTelegramDefaultContent,
|
||||
parse_mode: 'Markdown'
|
||||
}
|
||||
},
|
||||
'twitter': {
|
||||
component: Twitter,
|
||||
validations: {
|
||||
consumer_key: {required},
|
||||
consumer_secret: {required},
|
||||
token: {required},
|
||||
token_secret: {required},
|
||||
rate_limit: {},
|
||||
message: {},
|
||||
message_song_changed_live: {},
|
||||
message_live_connect: {},
|
||||
message_live_disconnect: {},
|
||||
message_station_offline: {},
|
||||
message_station_online: {}
|
||||
},
|
||||
defaultConfig: {
|
||||
consumer_key: '',
|
||||
consumer_secret: '',
|
||||
token: '',
|
||||
token_secret: '',
|
||||
rate_limit: 0,
|
||||
message: this.langTwitterDefaultMessage,
|
||||
message_song_changed_live: this.langTwitterSongChangedLiveMessage,
|
||||
message_live_connect: this.langTwitterDjOnMessage,
|
||||
message_live_disconnect: this.langTwitterDjOffMessage,
|
||||
message_station_offline: this.langTwitterStationOfflineMessage,
|
||||
message_station_online: this.langTwitterStationOnlineMessage
|
||||
}
|
||||
},
|
||||
'mastodon': {
|
||||
component: Mastodon,
|
||||
validations: {
|
||||
instance_url: {required},
|
||||
access_token: {required},
|
||||
rate_limit: {},
|
||||
visibility: {required},
|
||||
message: {},
|
||||
message_song_changed_live: {},
|
||||
message_live_connect: {},
|
||||
message_live_disconnect: {},
|
||||
message_station_offline: {},
|
||||
message_station_online: {}
|
||||
},
|
||||
defaultConfig: {
|
||||
instance_url: '',
|
||||
access_token: '',
|
||||
rate_limit: 0,
|
||||
visibility: 'public',
|
||||
message: this.langTwitterDefaultMessage,
|
||||
message_song_changed_live: this.langTwitterSongChangedLiveMessage,
|
||||
message_live_connect: this.langTwitterDjOnMessage,
|
||||
message_live_disconnect: this.langTwitterDjOffMessage,
|
||||
message_station_offline: this.langTwitterStationOfflineMessage,
|
||||
message_station_online: this.langTwitterStationOnlineMessage
|
||||
}
|
||||
},
|
||||
'google_analytics': {
|
||||
component: GoogleAnalytics,
|
||||
validations: {
|
||||
tracking_id: {required}
|
||||
},
|
||||
defaultConfig: {
|
||||
tracking_id: ''
|
||||
}
|
||||
},
|
||||
'matomo_analytics': {
|
||||
component: MatomoAnalytics,
|
||||
validations: {
|
||||
matomo_url: {required},
|
||||
site_id: {required},
|
||||
token: {},
|
||||
},
|
||||
defaultConfig: {
|
||||
matomo_url: '',
|
||||
site_id: '',
|
||||
token: ''
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
langPoweredByAzuraCast() {
|
||||
return this.$gettext('Powered by AzuraCast');
|
||||
},
|
||||
langDiscordDefaultContent() {
|
||||
return this.$gettext(
|
||||
'Now playing on %{ station }:',
|
||||
{'station': '{{ station.name }}'}
|
||||
);
|
||||
},
|
||||
langTelegramDefaultContent() {
|
||||
return this.$gettext(
|
||||
'Now playing on %{ station }: %{ title } by %{ artist }! Tune in now.',
|
||||
{
|
||||
station: '{{ station.name }}',
|
||||
title: '{{ now_playing.song.title }}',
|
||||
artist: '{{ now_playing.song.artist }}'
|
||||
}
|
||||
);
|
||||
},
|
||||
langTwitterDefaultMessage() {
|
||||
return this.$gettext(
|
||||
'Now playing on %{ station }: %{ title } by %{ artist }! Tune in now: %{ url }',
|
||||
{
|
||||
station: '{{ station.name }}',
|
||||
title: '{{ now_playing.song.title }}',
|
||||
artist: '{{ now_playing.song.artist }}',
|
||||
url: '{{ station.public_player_url }}'
|
||||
}
|
||||
);
|
||||
},
|
||||
langTwitterSongChangedLiveMessage() {
|
||||
return this.$gettext(
|
||||
'Now playing on %{ station }: %{ title } by %{ artist } with your host, %{ dj }! Tune in now: %{ url }',
|
||||
{
|
||||
station: '{{ station.name }}',
|
||||
title: '{{ now_playing.song.title }}',
|
||||
artist: '{{ now_playing.song.artist }}',
|
||||
dj: '{{ live.streamer_name }}',
|
||||
url: '{{ station.public_player_url }}'
|
||||
}
|
||||
);
|
||||
},
|
||||
langTwitterDjOnMessage() {
|
||||
return this.$gettext(
|
||||
'%{ dj } is now live on %{ station }! Tune in now: %{ url }',
|
||||
{
|
||||
dj: '{{ live.streamer_name }}',
|
||||
station: '{{ station.name }}',
|
||||
url: '{{ station.public_player_url }}'
|
||||
}
|
||||
);
|
||||
},
|
||||
langTwitterDjOffMessage() {
|
||||
return this.$gettext(
|
||||
'Thanks for listening to %{ station }!',
|
||||
{
|
||||
station: '{{ station.name }}',
|
||||
}
|
||||
);
|
||||
},
|
||||
langTwitterStationOfflineMessage() {
|
||||
return this.$gettext(
|
||||
'%{ station } is going offline for now.',
|
||||
{
|
||||
station: '{{ station.name }}'
|
||||
}
|
||||
);
|
||||
},
|
||||
langTwitterStationOnlineMessage() {
|
||||
return this.$gettext(
|
||||
'%{ station } is back online! Tune in now: %{ url }',
|
||||
{
|
||||
station: '{{ station.name }}',
|
||||
url: '{{ station.public_player_url }}'
|
||||
}
|
||||
);
|
||||
defaultConfig: {
|
||||
station_id: '',
|
||||
partner_id: '',
|
||||
partner_key: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetForm() {
|
||||
this.type = null;
|
||||
this.form = {
|
||||
name: null,
|
||||
triggers: [],
|
||||
config: {}
|
||||
};
|
||||
'discord': {
|
||||
component: Discord,
|
||||
validations: {
|
||||
webhook_url: {required},
|
||||
content: {},
|
||||
title: {},
|
||||
description: {},
|
||||
url: {},
|
||||
author: {},
|
||||
thumbnail: {},
|
||||
footer: {},
|
||||
},
|
||||
setType(type) {
|
||||
this.type = type;
|
||||
this.form.config = get(this.webhookConfig, [type, 'defaultConfig'], {});
|
||||
defaultConfig: {
|
||||
webhook_url: '',
|
||||
content: langDiscordDefaultContent,
|
||||
title: '{{ now_playing.song.title }}',
|
||||
description: '{{ now_playing.song.artist }}',
|
||||
url: '{{ station.listen_url }}',
|
||||
author: '{{ live.streamer_name }}',
|
||||
thumbnail: '{{ now_playing.song.art }}',
|
||||
footer: langPoweredByAzuraCast,
|
||||
}
|
||||
},
|
||||
'telegram': {
|
||||
component: Telegram,
|
||||
validations: {
|
||||
bot_token: {required},
|
||||
chat_id: {required},
|
||||
api: {},
|
||||
text: {required},
|
||||
parse_mode: {required}
|
||||
},
|
||||
getSubmittableFormData() {
|
||||
let formData = this.form;
|
||||
if (!this.isEditMode) {
|
||||
formData.type = this.type;
|
||||
}
|
||||
return formData;
|
||||
defaultConfig: {
|
||||
bot_token: '',
|
||||
chat_id: '',
|
||||
api: '',
|
||||
text: langTelegramDefaultContent,
|
||||
parse_mode: 'Markdown'
|
||||
}
|
||||
},
|
||||
'twitter': {
|
||||
component: Twitter,
|
||||
validations: {
|
||||
consumer_key: {required},
|
||||
consumer_secret: {required},
|
||||
token: {required},
|
||||
token_secret: {required},
|
||||
rate_limit: {},
|
||||
message: {},
|
||||
message_song_changed_live: {},
|
||||
message_live_connect: {},
|
||||
message_live_disconnect: {},
|
||||
message_station_offline: {},
|
||||
message_station_online: {}
|
||||
},
|
||||
populateForm(d) {
|
||||
this.type = d.type;
|
||||
this.form = {
|
||||
name: d.name,
|
||||
triggers: d.triggers,
|
||||
config: d.config
|
||||
};
|
||||
defaultConfig: {
|
||||
consumer_key: '',
|
||||
consumer_secret: '',
|
||||
token: '',
|
||||
token_secret: '',
|
||||
rate_limit: 0,
|
||||
message: langTwitterDefaultMessage,
|
||||
message_song_changed_live: langTwitterSongChangedLiveMessage,
|
||||
message_live_connect: langTwitterDjOnMessage,
|
||||
message_live_disconnect: langTwitterDjOffMessage,
|
||||
message_station_offline: langTwitterStationOfflineMessage,
|
||||
message_station_online: langTwitterStationOnlineMessage
|
||||
}
|
||||
},
|
||||
'mastodon': {
|
||||
component: Mastodon,
|
||||
validations: {
|
||||
instance_url: {required},
|
||||
access_token: {required},
|
||||
rate_limit: {},
|
||||
visibility: {required},
|
||||
message: {},
|
||||
message_song_changed_live: {},
|
||||
message_live_connect: {},
|
||||
message_live_disconnect: {},
|
||||
message_station_offline: {},
|
||||
message_station_online: {}
|
||||
},
|
||||
defaultConfig: {
|
||||
instance_url: '',
|
||||
access_token: '',
|
||||
rate_limit: 0,
|
||||
visibility: 'public',
|
||||
message: langTwitterDefaultMessage,
|
||||
message_song_changed_live: langTwitterSongChangedLiveMessage,
|
||||
message_live_connect: langTwitterDjOnMessage,
|
||||
message_live_disconnect: langTwitterDjOffMessage,
|
||||
message_station_offline: langTwitterStationOfflineMessage,
|
||||
message_station_online: langTwitterStationOnlineMessage
|
||||
}
|
||||
},
|
||||
'google_analytics': {
|
||||
component: GoogleAnalytics,
|
||||
validations: {
|
||||
tracking_id: {required}
|
||||
},
|
||||
defaultConfig: {
|
||||
tracking_id: ''
|
||||
}
|
||||
},
|
||||
'matomo_analytics': {
|
||||
component: MatomoAnalytics,
|
||||
validations: {
|
||||
matomo_url: {required},
|
||||
site_id: {required},
|
||||
token: {},
|
||||
},
|
||||
defaultConfig: {
|
||||
matomo_url: '',
|
||||
site_id: '',
|
||||
token: ''
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const triggerOptions = computed(() => {
|
||||
if (!type.value) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let webhookKeys = get(props.webhookTypes, [type.value, 'triggers'], []);
|
||||
return map(webhookKeys, (key) => {
|
||||
return {
|
||||
html:
|
||||
'<h6 class="font-weight-bold mb-0">' + props.triggerTitles[key] + '</h6>'
|
||||
+ '<p class="card-text small">' + props.triggerDescriptions[key] + '</p>',
|
||||
value: key
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
const typeTitle = computed(() => {
|
||||
return get(props.webhookTypes, [type.value, 'name'], '');
|
||||
});
|
||||
|
||||
const formComponent = computed(() => {
|
||||
return get(webhookConfig, [type.value, 'component'], Generic);
|
||||
});
|
||||
|
||||
const {
|
||||
loading,
|
||||
error,
|
||||
isEditMode,
|
||||
v$,
|
||||
resetForm,
|
||||
clearContents: originalClearContents,
|
||||
create,
|
||||
edit,
|
||||
doSubmit,
|
||||
close
|
||||
} = useBaseEditModal(
|
||||
props,
|
||||
emit,
|
||||
$modal,
|
||||
() => computed(() => {
|
||||
let validations = {
|
||||
name: {required},
|
||||
triggers: {},
|
||||
config: {}
|
||||
};
|
||||
|
||||
const triggerOptionsValue = triggerOptions.value;
|
||||
if (triggerOptionsValue.length > 0) {
|
||||
validations.triggers = {required};
|
||||
}
|
||||
|
||||
if (type.value !== null) {
|
||||
validations.config = get(
|
||||
webhookConfig,
|
||||
[type.value, 'validations'],
|
||||
{}
|
||||
);
|
||||
}
|
||||
|
||||
return validations;
|
||||
}),
|
||||
() => computed(() => {
|
||||
let newForm = {
|
||||
name: null,
|
||||
triggers: [],
|
||||
config: {}
|
||||
};
|
||||
|
||||
if (type.value !== null) {
|
||||
newForm.config = get(
|
||||
webhookConfig,
|
||||
[type.value, 'defaultConfig'],
|
||||
{}
|
||||
);
|
||||
}
|
||||
|
||||
return newForm;
|
||||
}),
|
||||
{
|
||||
populateForm: (data, formRef) => {
|
||||
type.value = data.type;
|
||||
formRef.value = {
|
||||
name: data.name,
|
||||
triggers: data.triggers,
|
||||
config: data.config
|
||||
};
|
||||
},
|
||||
getSubmittableFormData(formRef, isEditModeRef) {
|
||||
let formData = formRef.value;
|
||||
if (!isEditModeRef.value) {
|
||||
formData.type = type.value;
|
||||
}
|
||||
return formData;
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const langTitle = computed(() => {
|
||||
return isEditMode.value
|
||||
? $gettext('Edit Web Hook')
|
||||
: $gettext('Add Web Hook');
|
||||
});
|
||||
|
||||
const clearContents = () => {
|
||||
type.value = null;
|
||||
originalClearContents();
|
||||
};
|
||||
|
||||
const setType = (newType) => {
|
||||
type.value = newType;
|
||||
resetForm();
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
create,
|
||||
edit,
|
||||
close
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -182,6 +182,7 @@ export function useBaseEditModal(
|
|||
isEditMode,
|
||||
form,
|
||||
v$,
|
||||
resetForm,
|
||||
clearContents,
|
||||
create,
|
||||
edit,
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import {ref} from "vue";
|
||||
import {cloneDeep} from "lodash";
|
||||
import {resolveUnref} from "@vueuse/core";
|
||||
|
||||
export function useResettableRef(original) {
|
||||
const record = ref(cloneDeep(original));
|
||||
const record = ref(cloneDeep(resolveUnref(original)));
|
||||
|
||||
const reset = () => {
|
||||
record.value = cloneDeep(original);
|
||||
record.value = cloneDeep(resolveUnref(original));
|
||||
}
|
||||
|
||||
return {record, reset};
|
||||
|
|
|
@ -5,10 +5,12 @@ import {useAzuraCast} from "~/vendor/azuracast";
|
|||
import {useTranslate} from "~/vendor/gettext";
|
||||
import {useNotify} from "~/vendor/bootstrapVue";
|
||||
|
||||
const injectKey = 'axios';
|
||||
|
||||
/* Composition API Axios utilities */
|
||||
export function useAxios() {
|
||||
return {
|
||||
axios: inject('axios')
|
||||
axios: inject(injectKey)
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -57,5 +59,5 @@ export default function installAxios(vueApp) {
|
|||
|
||||
vueApp.use(VueAxios, axios);
|
||||
|
||||
vueApp.provide('axios', axios);
|
||||
vueApp.provide(injectKey, axios);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue