{% extends 'base.html' %} {% load i18n %} {% block body %} {% if STATEFUL_MODE != 'disabled' %}

{% trans "Management for:" %} {{ key }}

{% if not CONFIG_LOCK %}
{% trans "Getting Started" %}
  1. {% blocktrans %} Here is where you can store your Apprise configuration associated with the key {{key}}. {% endblocktrans %}
  2. {% blocktrans %} You can always refer to the Apprise Wiki if you're having troubles assembling your URL(s). {% endblocktrans %}
  3. {% blocktrans %} In the future you can return to this configuration screen at any time by placing the following into your browser: {% endblocktrans %} {{request.scheme}}://{{request.META.HTTP_HOST}}{{BASE_URL}}/cfg/{{key}}

{% blocktrans %}To get started, the first thing you want to do is define your configuration. Do this by clicking on the Configuration tab. {% endblocktrans %}

{% else %}
{% trans "Apprise Configuration is Locked" %}

{% 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 %}

{% endif %}
{% trans "Working With Your Configuration" %}

{% blocktrans %}The following command would cause apprise to directly notify all of your services:{% endblocktrans %}

apprise --body="Test Message" \
    apprise{% if request.is_secure %}s{% endif %}://{{request.META.HTTP_HOST}}{{BASE_URL}}/{{key}}?tags=all

{% if not CONFIG_LOCK %}

{% blocktrans %}The following command would cause apprise to retrieve the configuration loaded and send a test notification to all of your added services:{% endblocktrans %}

apprise --body="Test Message" --tag=all \
    --config={{request.scheme}}://{{request.META.HTTP_HOST}}{{BASE_URL}}/get/{{key}}

{% endif %}
{% trans "Loaded Configuration" %}
{% if not CONFIG_LOCK %}

{% blocktrans %}Define your configuration below:{% endblocktrans %}

{{ form_cfg }}

{% else %}
{% trans "Your Configuration Is Locked" %}

{% blocktrans %}Access to your configuration has been disabled by your administrator.{% endblocktrans %} {% endif %}

{% blocktrans %} You can send a notification using the loaded configuration: {% endblocktrans %}

{{ form_notify }}

{% else %}

{% trans "Persistent Store Endpoints" %}

{% blocktrans %}The administrator of this system has disabled persistent storage.{% endblocktrans %}

{% endif %} {% endblock %} {% block jsfooter %} {% if STATEFUL_MODE != 'disabled' %} async function main_init(){ // 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'); // 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; {% if not CONFIG_LOCK %} // Ensure no-config sections are visible document.querySelector('.no-config') .style.display = null; {% endif %} // 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; } // 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); }) } }); // 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); }); urlList.appendChild(li); }); // Store our new list document.querySelector('#url-list-progress').style.display = 'none'; document.querySelector('#url-list').textContent = '' if(urlList.childNodes.length > 0) { // Ensure has-config sections are visible document.querySelector('.has-config') .style.display = null; // Remove our restrictions on sending notifications document.querySelector('.config-overview li a[href="#notify"]') .parentNode.classList.remove('disabled'); {% if not CONFIG_LOCK %} // Disable any no-config entries document.querySelector('.no-config') .style.display = 'none'; {% 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' }, }); 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." %}' } return null; } 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; } } 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' ); } }); }); return false; } } /* Initialize our page */ main_init(); {% if not CONFIG_LOCK %} /* Initialze our configuration */ config_init(); {% endif %} notify_init(); {% endif %} {% endblock %} {% block onload %} {% if STATEFUL_MODE != 'disabled' %} {{ 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'; {% endif %} {% endblock %}