2019-10-27 04:53:40 +01:00
{% extends 'base.html' %}
{% load i18n %}
{% block body %}
2020-09-03 18:01:03 +02:00
{% if STATEFUL_MODE != 'disabled' %}
2020-01-19 02:26:40 +01:00
< h4 > {% trans "Management for:" %} < em > {{ key }}< / em > < / h4 >
2019-10-28 00:41:02 +01:00
< div class = "row" >
< div class = "col s12" >
< ul class = "tabs config-overview" >
2020-01-19 02:26:40 +01:00
< li class = "tab col s4" > < a class = "active" href = "#overview" > < i class = "material-icons" > info< / i >
{% trans "Overview" %}< / a > < / li >
2021-11-06 22:21:41 +01:00
< li class = "tab {% if CONFIG_LOCK %}tab-locked {% endif %}col s4" > < a href = "#config" > < i class = "material-icons" > {% if not CONFIG_LOCK %}settings{% else %}lock{% endif %}< / i > {%trans "Configuration" %}< / a >
2020-01-19 02:26:40 +01:00
< / li >
< li class = "tab col s4" > < a href = "#notify" > < i class = "material-icons" > announcement< / i > {%trans "Notifications" %}< / a >
< / li >
2019-10-28 00:41:02 +01:00
< / ul >
< / div >
< div id = "overview" class = "col s12" >
2021-11-06 22:21:41 +01:00
{% if not CONFIG_LOCK %}
2019-10-28 00:41:02 +01:00
< div class = "section" >
2020-01-19 02:26:40 +01:00
< h5 > {% trans "Getting Started" %}< / h5 >
< ol >
< li >
{% blocktrans %}
Here is where you can store your Apprise configuration associated with the key < code > {{key}}< / code > .
{% endblocktrans %}
< / li >
< li >
{% blocktrans %}
2021-11-11 04:07:21 +01:00
In the future you can return to this configuration screen at any time by placing the following into your
browser:
2020-01-19 02:26:40 +01:00
{% endblocktrans %}
2021-11-11 04:07:21 +01:00
< code > {{request.scheme}}://{{request.META.HTTP_HOST}}{{BASE_URL}}/cfg/{{key}}< / code >
2020-01-19 02:26:40 +01:00
< / li >
< li >
{% blocktrans %}
2021-11-11 04:07:21 +01:00
Use the < strong > < i class = "material-icons" > settings< / i > Configuration< / strong > section to prepare and save your Apprise configuration.
{% endblocktrans %}
< ul >
< li >
{% blocktrans %}
< i class = "material-icons" > lightbulb_outline< / i > 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).
{% endblocktrans %}
< / li >
< / ul >
< / li >
< li >
{% blocktrans %}
Use the < strong > < i class = "material-icons" > announcement< / i > Notifications< / strong > section to test out your saved configuration.
2020-01-19 02:26:40 +01:00
{% endblocktrans %}
< / li >
< / ol >
< / div >
< div class = "section no-config" >
< div class = "divider" > < / div >
2021-11-14 16:48:31 +01:00
< p >
< i class = "material-icons info" > info< / i >
{% blocktrans %}Once you have successfully load < i > at least one Apprise URL< / i > on the < strong > < i class = "material-icons" > settings< / i > Configuration< / strong > section, your loaded entries will display here.
{% endblocktrans %}
< / p >
2020-01-19 02:26:40 +01:00
< div class = "divider" > < / div >
< / div >
2021-11-06 22:21:41 +01:00
{% else %}
< div class = "section" >
< h5 > {% trans "Apprise Configuration is Locked" %}< / h5 >
< p >
{% blocktrans %}At this time, the administrator of this server has locked down all configuration. This means
That pre-created configuration is securely hidden for the purpose of notification transmission only.
New configuration can not be set, and existing configuration can not be modified or viewed.
{% endblocktrans %}< / p >
< / div >
{% endif %}
2020-01-19 02:26:40 +01:00
< div class = "has-config" >
< div class = "section" >
2021-11-11 04:07:21 +01:00
< h5 > {% trans "Working Remotely With Your Configuration" %}< / h5 >
2021-11-06 22:21:41 +01:00
< p >
{% blocktrans %}The following command would cause apprise to directly notify all of your services:{% endblocktrans %}
< br / >
< pre > < code class = "bash" > apprise --body="Test Message" \< br / >
apprise{% if request.is_secure %}s{% endif %}://{{request.META.HTTP_HOST}}{{BASE_URL}}/{{key}}?tags=all< / code > < / pre >
< / p >
{% if not CONFIG_LOCK %}
< p >
2020-01-19 02:26:40 +01:00
{% blocktrans %}The following command would cause apprise to retrieve the configuration loaded and
send a test notification to all of your added services:{% endblocktrans %}
< br / >
< pre > < code class = "bash" > apprise --body="Test Message" --tag=all \< br / >
2020-09-03 18:01:03 +02:00
--config={{request.scheme}}://{{request.META.HTTP_HOST}}{{BASE_URL}}/get/{{key}}< / code > < / pre >
2021-11-06 22:21:41 +01:00
< / p >
{% endif %}
2020-01-19 02:26:40 +01:00
< / div >
< div class = "section" >
< h5 > {% trans "Loaded Configuration" %}< / h5 >
< div id = "url-list" > < / div >
< div id = "url-list-progress" class = "progress" style = "width:70%" >
< div class = "indeterminate" > < / div >
< / div >
< / div >
2019-10-27 04:53:40 +01:00
< / div >
2019-10-28 00:41:02 +01:00
< / div >
< div id = "config" class = "col s12" >
2021-11-06 22:21:41 +01:00
{% if not CONFIG_LOCK %}
2020-01-18 21:32:53 +01:00
< p >
{% blocktrans %}Define your configuration below:{% endblocktrans %}
< form id = "addconfig" action = "{% url " add " key % } " method = "post" >
{{ form_cfg }}
2020-01-19 02:26:40 +01:00
< button class = "btn waves-effect waves-light" type = "submit" name = "action" > {% trans "Save Configuration" %}
< i class = "material-icons right" > save< / i >
2020-01-18 21:32:53 +01:00
< / button >
< / form >
< / p >
2021-11-06 22:21:41 +01:00
{% else %}
< h5 > {% trans "Your Configuration Is Locked" %}< / h5 >
< p > {% blocktrans %}Access to your configuration has been disabled by your administrator.{% endblocktrans %}
{% endif %}
2019-10-27 04:53:40 +01:00
< / div >
2021-11-06 22:21:41 +01:00
2019-10-28 00:41:02 +01:00
< 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 }}
2020-01-19 02:26:40 +01:00
< button class = "btn waves-effect waves-light" type = "submit" name = "action" > {% trans "Send Notification" %}
2019-10-28 00:41:02 +01:00
< i class = "material-icons right" > send< / i >
< / button >
< / form >
< / p >
< / div >
< / div >
2020-09-03 18:01:03 +02:00
{% else %}
< div class = "section" >
< h4 > {% trans "Persistent Store Endpoints" %}< / h4 >
< p > {% blocktrans %}The administrator of this system has disabled persistent storage.{% endblocktrans %}< / p >
< / div >
{% endif %}
2019-10-28 00:41:02 +01:00
{% endblock %}
{% block jsfooter %}
2021-11-06 22:21:41 +01:00
{% if STATEFUL_MODE != 'disabled' %}
async function main_init(){
2019-10-28 00:41:02 +01:00
// 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');
2020-01-19 02:26:40 +01:00
// Disable any has-config entries
document.querySelector('.has-config')
.style.display = 'none';
// Ensure we show our progress loader and reset our url list
document.querySelector('#url-list').textContent = ''
document.querySelector('#url-list-progress').style.display = null;
2021-11-06 22:21:41 +01:00
{% if not CONFIG_LOCK %}
2020-01-19 02:26:40 +01:00
// Ensure no-config sections are visible
document.querySelector('.no-config')
.style.display = null;
2021-11-06 22:21:41 +01:00
{% endif %}
2020-01-19 02:26:40 +01:00
2021-11-06 22:21:41 +01:00
// perform a tag retrieval; start with 'all'
let tags = ['all'];
let jsonResponse = await fetch('{% url "json_urls" key %}/?privacy=1', {
method: 'GET',
})
if(jsonResponse.status != 200) {
// Take an early exit
document.querySelector('#url-list-progress').style.display = 'none';
document.querySelector('#url-list').textContent = '{% trans "An error occurred retrieving the list of loaded Apprise URL(s)" %}'
return;
2019-10-28 00:41:02 +01:00
}
2021-11-06 22:21:41 +01:00
// Initialize our tags making it easy for an end user to
// choose from. Tags are based off ones found in the saved
// configuration.
const data = await jsonResponse.json();
let external_data = tags.concat(data.tags).reduce(function(result, item) {
result[item] = null;
return result;
}, {})
M.Chips.init(document.querySelectorAll('.chips'), {
placeholder: 'Optional Tag',
secondaryPlaceholder: 'Another Tag',
autocompleteOptions: {
data: external_data,
minLength: 0
},
onChipAdd: function(e, chip) {
var $this = this;
$this.chipsData.forEach(function(e, index) {
if(!(e.tag in external_data))
$this.deleteChip(index);
})
}
});
2019-10-28 00:41:02 +01:00
2021-11-06 22:21:41 +01:00
// Now build our our loaded list of configuration for our welcome page
let urlList = document.createElement('ul');
// Create a list item for each url retrieved
data.urls.forEach(function (entry) {
let code = document.createElement('code');
let li = document.createElement('li');
code.textContent = entry.url;
li.setAttribute('class', 'card-panel');
li.appendChild(code);
// Get our tags associate with the URL
entry.tags.forEach(function (tag) {
let chip = document.createElement('div');
chip.setAttribute('class', 'chip');
chip.textContent = `🏷️ ${tag}`;
li.appendChild(chip);
});
2020-09-02 23:42:17 +02:00
2021-11-06 22:21:41 +01:00
urlList.appendChild(li);
});
2020-09-02 23:42:17 +02:00
2021-11-06 22:21:41 +01:00
// Store our new list
document.querySelector('#url-list-progress').style.display = 'none';
document.querySelector('#url-list').textContent = ''
if(urlList.childNodes.length > 0) {
2019-10-28 00:41:02 +01:00
2020-01-19 02:26:40 +01:00
// Ensure has-config sections are visible
document.querySelector('.has-config')
.style.display = null;
2021-11-06 22:21:41 +01:00
// Remove our restrictions on sending notifications
document.querySelector('.config-overview li a[href="#notify"]')
.parentNode.classList.remove('disabled');
{% if not CONFIG_LOCK %}
2020-01-19 02:26:40 +01:00
// Disable any no-config entries
document.querySelector('.no-config')
.style.display = 'none';
2021-11-06 22:21:41 +01:00
{% endif %}
// Save our list to the screen
document.querySelector('#url-list').appendChild(urlList);
{% if not CONFIG_LOCK %}
//
// Load our configuration now into the configuration tab
//
let response = await fetch('{% url "get" key %}', {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
2020-01-12 05:36:19 +01:00
});
2021-11-06 22:21:41 +01:00
if(response.status == 204)
{
// no problem; we simply have no content to retrieve
return '';
}
else if(response.status == 200)
{
// configuration found
// get our results
let result = await response.json();
// Set our configuration so it's visible
document.querySelector('#id_config').value = result.config;
// Set our format
document.querySelector('#id_format').value = result.format;
// dispatch our event to update our select box
if (typeof(Event) === 'function') {
var event = new Event('change');
} else { // for IE11
var event = document.createEvent('Event');
event.initEvent('change', true, true);
}
document.querySelector('#id_format').dispatchEvent(event);
}
{% endif %}
} else {
document.querySelector('#url-list').textContent = '{% trans "There are no Apprise URL(s) loaded." %}'
2019-10-28 00:41:02 +01:00
}
2021-11-06 22:21:41 +01:00
2019-10-28 00:41:02 +01:00
return null;
}
2021-11-06 22:21:41 +01:00
function config_init() {
// 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));
content = document.querySelector('#id_config')
.value.replace(/^\s+|\s+$/gm,'');
if(content.length) {
// perform our status check
let response = fetch('{% url "add" key %}', {
method: 'POST',
body: body,
}).then(function(response) {
if(response.status == 200)
{
// update our settings
main_init();
// user notification
Swal.fire(
'{% trans "Save" %}',
'{% trans "Successfully saved the specified URL(s)." %}',
'success'
);
} else if(response.status == 500) {
// Disk issue
Swal.fire(
'{% trans "Save" %}',
'{% trans "There was an issue writing the configuration to disk. Check your file permissions and try again." %}',
'error'
);
} else {
// user notification
Swal.fire(
'{% trans "Save" %}',
'{% trans "Failed to save the specified URL(s). Check your syntax and try again." %}',
'error'
);
}
});
} else {
// Perform Delete
// perform our status check
let response = fetch('{% url "del" key %}', {
method: 'POST',
body: body,
}).then(function(response) {
if(response.status == 200 || response.status == 204)
{
// update our settings
main_init();
// user notification
Swal.fire(
'{% trans "Delete" %}',
'{% trans "Successfully removed configuration." %}',
'success'
);
} else {
// user notification
Swal.fire(
'{% trans "Delete" %}',
'{% trans "There was an issue removing the configuration." %}',
'error'
);
}
});
}
return false;
}
2019-10-28 00:41:02 +01:00
}
2021-11-06 22:21:41 +01:00
function notify_init() {
// 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-committed 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 notification
Swal.fire(
'{% trans "Notification" %}',
'{% trans "Sending notification(s)..." %}',
);
Swal.showLoading()
let response = fetch('{% url "notify" key %}', {
method: 'POST',
body: body,
headers: {
'Accept': 'text/html',
'X-Apprise-Log-Level': 'info'
}
}).then(function(response) {
response.text().then(function (html) {
if(response.status == 200)
{
// user notification
Swal.fire(
'{% trans "Notification" %}',
'{% trans "Successfully sent the notification(s)." %}' + html,
'success'
);
} else if(response.status == 424) {
// user notification
Swal.fire(
'{% trans "Notification" %}',
'{% trans "One or more of the notification(s) were not sent." %}' + html,
'warning'
);
} else {
// user notification
Swal.fire(
'{% trans "Notification" %}',
'{% trans "Failed to send the notification(s)." %}' + html,
'error'
);
}
});
2020-01-12 05:36:19 +01:00
});
2021-11-06 22:21:41 +01:00
return false;
2020-01-12 05:36:19 +01:00
}
2019-10-28 00:41:02 +01:00
}
2021-11-06 22:21:41 +01:00
/* Initialize our page */
main_init();
{% if not CONFIG_LOCK %}
/* Initialze our configuration */
config_init();
{% endif %}
notify_init();
{% endif %}
2019-10-27 04:53:40 +01:00
{% endblock %}
2020-01-12 05:36:19 +01:00
{% block onload %}
2021-11-06 22:21:41 +01:00
{% if STATEFUL_MODE != 'disabled' %}
2020-01-12 05:36:19 +01:00
{{ 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';
2021-11-06 22:21:41 +01:00
{% endif %}
2020-01-12 05:36:19 +01:00
{% endblock %}