451 lines
12 KiB
Vue
451 lines
12 KiB
Vue
<template>
|
|
<modal-form
|
|
ref="$modal"
|
|
:loading="loading"
|
|
:title="langTitle"
|
|
:error="error"
|
|
:disable-save-button="v$.$invalid"
|
|
@submit="doSubmit"
|
|
@hidden="clearContents"
|
|
>
|
|
<type-select
|
|
v-if="!type"
|
|
:webhook-types="webhookTypes"
|
|
@select="setType"
|
|
/>
|
|
<b-tabs
|
|
v-else
|
|
lazy
|
|
content-class="mt-3"
|
|
pills
|
|
>
|
|
<b-tab active>
|
|
<template #title>
|
|
{{ $gettext('Basic Info') }}
|
|
</template>
|
|
|
|
<basic-info
|
|
:trigger-options="triggerOptions"
|
|
:form="v$"
|
|
/>
|
|
</b-tab>
|
|
<b-tab :title="typeTitle">
|
|
<component
|
|
:is="formComponent"
|
|
:now-playing-url="nowPlayingUrl"
|
|
:form="v$"
|
|
/>
|
|
</b-tab>
|
|
</b-tabs>
|
|
</modal-form>
|
|
</template>
|
|
|
|
<script setup>
|
|
import {required} from '@vuelidate/validators';
|
|
import TypeSelect from "./Form/TypeSelect";
|
|
import BasicInfo from "./Form/BasicInfo";
|
|
import {get, map} from "lodash";
|
|
import Generic from "./Form/Generic";
|
|
import Email from "./Form/Email";
|
|
import Tunein from "./Form/Tunein";
|
|
import Discord from "./Form/Discord";
|
|
import Telegram from "./Form/Telegram";
|
|
import Twitter from "./Form/Twitter";
|
|
import GoogleAnalyticsV3 from "./Form/GoogleAnalyticsV3";
|
|
import GoogleAnalyticsV4 from "./Form/GoogleAnalyticsV4";
|
|
import MatomoAnalytics from "./Form/MatomoAnalytics";
|
|
import Mastodon from "./Form/Mastodon";
|
|
import {baseEditModalProps, useBaseEditModal} from "~/functions/useBaseEditModal";
|
|
import {computed, ref} from "vue";
|
|
import {useTranslate} from "~/vendor/gettext";
|
|
import ModalForm from "~/components/Common/ModalForm.vue";
|
|
|
|
const props = defineProps({
|
|
...baseEditModalProps,
|
|
nowPlayingUrl: {
|
|
type: String,
|
|
required: true
|
|
},
|
|
webhookTypes: {
|
|
type: Object,
|
|
required: true
|
|
},
|
|
triggerTitles: {
|
|
type: Object,
|
|
required: true
|
|
},
|
|
triggerDescriptions: {
|
|
type: Object,
|
|
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: {},
|
|
},
|
|
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: 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}
|
|
},
|
|
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: {}
|
|
},
|
|
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: GoogleAnalyticsV3,
|
|
validations: {
|
|
tracking_id: {required}
|
|
},
|
|
defaultConfig: {
|
|
tracking_id: ''
|
|
}
|
|
},
|
|
'google_analytics_v4': {
|
|
component: GoogleAnalyticsV4,
|
|
validations: {
|
|
api_secret: {required},
|
|
measurement_id: {required}
|
|
},
|
|
defaultConfig: {
|
|
api_secret: '',
|
|
measurement_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>
|