apprise-api/apprise_api/api/templates/config.html

316 lines
9.2 KiB
HTML

{% extends 'base.html' %}
{% load i18n %}
{% block body %}
<h3>{% trans "Management for:" %} <em>{{ key }}</em></h3>
<div class="row">
<div class="col s12">
<ul class="tabs config-overview">
<li class="tab col s4"><a class="active" href="#overview">{% trans "Overview" %}</a></li>
<li class="tab col s4"><a href="#config">{%trans "Configuration" %}</a></li>
<li class="tab col s4"><a href="#notify">{%trans "Notifications" %}</a></li>
</ul>
</div>
<div id="overview" class="col s12">
<p>
{% blocktrans %}
Here is where you can store your configuration so that it can be accessed by Apprise. You can always refer to the
<a href="https://github.com/caronc/apprise/wiki#notification-services">Apprise Wiki</a> if you're having troubles
assembling your URL(s).
You have chosen to associate your configuration with the key <code>{{key}}</code>. If anything was previously
associated with this key, it will be replaced if you continue.
{% endblocktrans %}
</p>
<p>
{% blocktrans %}
In the future you can return to this configuration screen at any time by placing the following into your
browser:{% endblocktrans %}
<br /><code>{{request.scheme}}://{{request.META.HTTP_HOST}}{{request.path}}</code>
</p>
<div class="section">
{% blocktrans %}For example, the following command would cause apprise to retrieve the configuration loaded and
send a test notification to all of your added services:{% endblocktrans %}
<br /><code>apprise --body="Test Message" --tag=all --config={{request.scheme}}://{{request.META.HTTP_HOST}}{% url "get" key %}</code>
</div>
</div>
<div id="config" class="col s12">
<div class="section">
<h5>{% trans "Option 1: Set By URL(s)" %}</h5>
<p>
{% blocktrans %}
Use a comma and/or space to separate one Apprise URL from another.
{% endblocktrans %}
<form id="addurl" action="{% url "add" key %}" method="post">
{{ form_url }}
<button class="btn waves-effect waves-light" type="submit" name="action">{% trans "Submit" %}
<i class="material-icons right">send</i>
</button>
</form>
</p>
</div>
<div class="section">
<h5>{% trans "Option 2: Set By Config" %}</h5>
<p>
{% blocktrans %}
This option grants you a bit more flexability because you can additionally associate tags with your URLs. Those
using YAML configuration can also alter the Apprise Asset object as well for a more customized look and feel.
{% endblocktrans %}
<form id="addconfig" action="{% url "add" key %}" method="post">
{{ form_cfg }}
<button class="btn waves-effect waves-light" type="submit" name="action">{% trans "Submit" %}
<i class="material-icons right">send</i>
</button>
</form>
</p>
</div>
</div>
<div id="notify" class="col s12">
<p>
{% blocktrans %}
You can send a notification using the loaded configuration:
{% endblocktrans %}
<form id="donotify" action="{% url "notify" key %}" method="post">
{{ form_notify }}
<button class="btn waves-effect waves-light" type="submit" name="action">{% trans "Submit" %}
<i class="material-icons right">send</i>
</button>
</form>
</p>
</div>
</div>
{% endblock %}
{% block jsfooter %}
async function update() {
// disable the notification tab until we know for certain
// a notification is possible
document.querySelector('.config-overview li a[href="#notify"]')
.parentNode.classList.add('disabled');
// perform our status check
let response = await fetch('{% url "get" key %}', {
method: 'POST',
});
let result = await response;
if(response.status == 204)
{
// no problem; we simply have no content to retrieve
return '';
}
else if(response.status == 200)
{
// configuration found
// Remove our restrictions on sending notifications
document.querySelector('.config-overview li a[href="#notify"]')
.parentNode.classList.remove('disabled');
// Set our configuration so it's visible
response.text().then(function (text) {
document.querySelector('#id_config').value = text;
});
// perform a tag retrieval; start with 'all'
let tags = ['all'];
let jsonResponse = fetch('{% url "json_urls" key %}', {
method: 'GET',
}).then(function(jsonResponse) {
return jsonResponse.json();
}).then(function (data) {
// Initialize our tags making it easy for an end user to
// choose from. Tags are based off ones found in the saved
// configuration.
M.Chips.init(document.querySelectorAll('.chips'), {
placeholder: 'Optional Tag',
secondaryPlaceholder: 'Another Tag',
autocompleteOptions: {
data: tags.concat(data.tags).reduce(function(result, item) {
result[item] = null;
return result;
}, {}),
limit: Infinity,
minLength: 1
}
});
}).catch(function (err) {
// There was an error
});
return response;
}
// if we reach here, we failed
return null;
}
update();
// over-ride manual submit for a nicer user experience
document.querySelector('#addurl').onsubmit = function(event) {
event.preventDefault();
const form = this;
const body = new URLSearchParams(new FormData(form));
// perform our status check
let response = fetch('{% url "add" key %}', {
method: 'POST',
body: body,
}).then(function(response) {
if(response.status == 200)
{
// update our settings
update();
// reset our form
form.reset();
Swal.fire(
'Save',
'Successfully saved the specified URL(s).',
'success'
);
} else {
Swal.fire(
'Save',
'Failed to save the specified URL(s).',
'error'
);
}
});
return false;
}
// over-ride manual submit for a nicer user experience
document.querySelector('#addconfig').onsubmit = function(event) {
event.preventDefault();
const form = this;
const body = new URLSearchParams(new FormData(form));
// perform our status check
let response = fetch('{% url "add" key %}', {
method: 'POST',
body: body,
}).then(function(response) {
if(response.status == 200)
{
// update our settings
update();
// user notification
Swal.fire(
'Save',
'Successfully saved the specified URL(s).',
'success'
);
} else {
// user notification
Swal.fire(
'Save',
'Failed to save the specified URL(s).',
'error'
);
}
});
return false;
}
// over-ride manual submit for a nicer user experience
document.querySelector('#donotify').onsubmit = function(event) {
event.preventDefault();
const chipElement = document.querySelector('.chips');
chipElement.querySelector('.chips');
const chipInput = document.querySelector('.chips > input');
if(chipInput.value) {
// This code just handles text typed in the tag section that was
// not submitted. This forces any lingering un-commited text
// into a tag just prior to it's submission
const ev = new KeyboardEvent('keydown', {
altKey:false,
bubbles: true,
cancelBubble: false,
cancelable: true,
charCode: 0,
code: "Enter",
composed: true,
ctrlKey: false,
currentTarget: null,
defaultPrevented: true,
detail: 0,
eventPhase: 0,
isComposing: false,
isTrusted: true,
key: "Enter",
keyCode: 13,
location: 0,
metaKey: false,
repeat: false,
returnValue: false,
shiftKey: false,
type: "keydown",
which: 13
});
chipInput.dispatchEvent(ev);
}
// store tags (as comma separated string) from materialize chip type into form
document.querySelector('#id_tag').value = M.Chips.getInstance(chipElement).chipsData.reduce(
function(s, a){
s.push(a.tag)
return s;
}, []).join(",")
const form = this;
const body = new URLSearchParams(new FormData(form));
// perform our status check
let response = fetch('{% url "notify" key %}', {
method: 'POST',
body: body,
}).then(function(response) {
if(response.status == 200)
{
// user notification
Swal.fire(
'Notification',
'Successfully sent the notification(s).',
'success'
);
} else {
// user notification
Swal.fire(
'Notification',
'Failed to send the notification(s).',
'error'
);
}
});
return false;
}
{% endblock %}
{% block onload %}
{{ block.super }}
document.querySelector('label [for="id_tag"]')
{
// create a new div with the class 'chips' assigned to it
const element = document.createElement('div')
let refNode = document.querySelector('label[for="id_tag"]')
element.classList.add("chips")
element.style.margin = '0'
refNode.parentNode.insertBefore(element, refNode.nextSibling)
}
// Hide tag field since we use the pretty Materialize Chip setup instead
document.querySelector('#id_tag').style.display = 'none';
{% endblock %}