Files
wizarr/app/templates/modals/create-notification-agent.html
Jacob Swanson 7f64f558dc Add Telegram notification support
Introduces Telegram as a notification agent, including backend logic, form fields, and database columns for bot token and chat ID. Updates creation and editing flows, notification service, and UI to support Telegram integration. Includes a migration to add the new fields to the Notification model.
2026-01-23 22:03:05 -06:00

221 lines
12 KiB
HTML

<div class="relative modal-container"
aria-labelledby="modal-title"
role="dialog"
aria-modal="true">
<!--
Background backdrop, show/hide based on modal state.
Entering: "ease-out duration-300"
From: "opacity-0"
To: "opacity-100"
Leaving: "ease-in duration-200"
From: "opacity-100"
To: "opacity-0"
-->
<div class="fixed inset-0 modal-backdrop transition-opacity"></div>
<div class="fixed inset-0 z-10 overflow-y-auto ">
<div class="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
<!--
Modal panel, show/hide based on modal state.
Entering: "ease-out duration-300"
From: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
To: "opacity-100 translate-y-0 sm:scale-100"
Leaving: "ease-in duration-200"
From: "opacity-100 translate-y-0 sm:scale-100"
To: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
-->
<div class="relative transform overflow-hidden rounded-lg bg-white text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg">
<div class="bg-white px-4 pb-4 pt-5 sm:p-6 sm:pb-4 dark:bg-gray-800">
<div class="flex justify-between items-center pb-3">
<h1 class="text-xl font-bold leading-tight tracking-tight text-gray-900 md:text-2xl dark:text-white">
{{ _("New Agent") }}
</h1>
</div>
<p class="mt-2 pb-2 text-sm text-red-600 dark:text-red-500">
<span class="font-medium">{{ error }}</span>
</p>
<form class="space-y-4 md:space-y-6"
hx-post="{{ url_for(request.endpoint) }}"
hx-target="#tab-body"
hx-swap="innerHTML">
<div>
<label for="name"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Name</label>
<input type="text"
name="name"
id="name"
placeholder='e.g. "My Agent"'
class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary focus:border-primary block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
required>
</div>
<div>
<label for="notification_service"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">
Notification
Service
</label>
<select name="notification_service"
id="notification_service"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary focus:border-primary block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
onchange="toggleService(this.value)">
<option selected>Choose a service</option>
<option value="apprise">Apprise</option>
<option value="discord">Discord</option>
<option value="notifiarr">Notifiarr</option>
<option value="ntfy">Ntfy</option>
<option value="telegram">Telegram</option>
</select>
</div>
<div id="notifiarrSection"
class="notificationAgentInfo"
style="display: none">
<label for="channel_id"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">{{ _("Channel ID") }}</label>
<input type="text"
name="channel_id"
id="channel_id"
class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary focus:border-primary block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" />
</div>
<div id="telegramSection"
class="notificationAgentInfo"
style="display: none">
<label for="telegram_bot_token"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">{{ _("Bot Token") }}</label>
<input type="password"
name="telegram_bot_token"
id="telegram_bot_token"
class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary focus:border-primary block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
<label for="telegram_chat_id"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">{{ _("Chat ID") }}</label>
<input type="text"
name="telegram_chat_id"
id="telegram_chat_id"
class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary focus:border-primary block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" />
</div>
<div id="credentialsSection"
class="notificationAgentInfo"
style="display: none">
<label for="username"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">
{{ _("Username (optional)") }}
</label>
<input type="text"
name="username"
id="username"
class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary focus:border-primary block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
<label for="password"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">
{{ _("Password (optional)") }}
</label>
<input type="password"
name="password"
id="password"
class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary focus:border-primary block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
</div>
<div>
<label for="url"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">{{ _("Agent URL") }}</label>
<input type="text"
name="url"
id="url"
placeholder="e.g. https://example.com"
class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary focus:border-primary block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
required>
</div>
<div>
<label class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">{{ _("Notification Events") }}</label>
<div class="space-y-2">
<div class="flex items-center">
<input type="checkbox"
name="event_user_joined"
id="event_user_joined"
value="user_joined"
checked
class="w-4 h-4 text-primary bg-gray-100 border-gray-300 rounded focus:ring-primary dark:focus:ring-primary dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
<label for="event_user_joined"
class="ml-2 text-sm font-medium text-gray-900 dark:text-gray-300">
{{ _("User Joined") }}
</label>
</div>
<div class="flex items-center">
<input type="checkbox"
name="event_update_available"
id="event_update_available"
value="update_available"
checked
class="w-4 h-4 text-primary bg-gray-100 border-gray-300 rounded focus:ring-primary dark:focus:ring-primary dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
<label for="event_update_available"
class="ml-2 text-sm font-medium text-gray-900 dark:text-gray-300">
{{ _("Update Available") }}
</label>
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:flex sm:flex-row-reverse sm:px-6 dark:bg-gray-800">
<button type="submit"
class="inline-flex w-full justify-center rounded-md bg-primary px-3 py-2 text-sm font-semibold text-white shadow-xs hover:bg-primary_hover sm:ml-3 sm:w-auto">
{{ _("Test & Create Agent") }}
</button>
<button onclick="closeModal()"
type="button"
class="mt-3 inline-flex w-full justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-xs ring-1 ring-inset ring-gray-300 hover:bg-gray-50 sm:mt-0 sm:w-auto">
{{ _("Cancel") }}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script>
//Function closeModal
function closeModal() {
//Delete Everything within the div "create-modal"
document.getElementById('create-modal').innerHTML = '';
}
function toggleService(value) {
const notificationAgentInfo = document.getElementsByClassName('notificationAgentInfo')
for (let i = 0; i < notificationAgentInfo.length; i++) {
notificationAgentInfo[i].style.display = 'none';
}
// Trigger sections
if (value === 'ntfy') {
credentialsSection.style.display = 'block';
} else if (value === "notifiarr") {
notifiarrSection.style.display = 'block';
} else if (value === "telegram") {
telegramSection.style.display = 'block';
}
// Trigger required channel_id
if (value === 'notifiarr') {
document.getElementById("channel_id").required = true
} else {
document.getElementById("channel_id").required = false
}
// Trigger required telegram fields
if (value === 'telegram') {
document.getElementById("telegram_bot_token").required = true
document.getElementById("telegram_chat_id").required = true
} else {
document.getElementById("telegram_bot_token").required = false
document.getElementById("telegram_chat_id").required = false
}
// Adjust placeholder text
const urlEle = document.getElementById('url');
if (value === 'apprise') {
urlEle.placeholder = "e.g. apprise://hostname/token";
} else {
urlEle.placeholder = "e.g. https://example.com";
}
}
</script>