Improved tag selection on Review tab (#179)

This commit is contained in:
Chris Caron 2024-03-16 16:33:00 -04:00 committed by GitHub
parent 2c7f7b36fe
commit 585e514b68
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 182 additions and 78 deletions

View File

@ -8,9 +8,9 @@
<ul class="tabs config-overview"> <ul class="tabs config-overview">
<li class="tab col s3"><a class="active" href="#overview"><i class="material-icons">info</i> <li class="tab col s3"><a class="active" href="#overview"><i class="material-icons">info</i>
{% trans "Overview" %}</a></li> {% trans "Overview" %}</a></li>
<li class="tab {% if CONFIG_LOCK %}tab-locked {% endif %}col s3"><a href="#config"><i class="material-icons">{% if not CONFIG_LOCK %}settings{% else %}lock{% endif %}</i> {%trans "Configuration" %}</a> <li class="tab {% if CONFIG_LOCK %}disabled {% endif %}col s3"><a href="#config"><i class="material-icons">{% if not CONFIG_LOCK %}settings{% else %}lock{% endif %}</i> {%trans "Configuration" %}</a>
</li> </li>
<li class="tab {% if CONFIG_LOCK %}tab-locked {% endif %}col s3"><a href="#review"><i class="material-icons">{% if not CONFIG_LOCK %}web{% else %}lock{% endif %}</i> {%trans "Review" %}</a> <li class="tab {% if CONFIG_LOCK %}disabled {% endif %}col s3"><a href="#review"><i class="material-icons">{% if not CONFIG_LOCK %}web{% else %}lock{% endif %}</i> {%trans "Review" %}</a>
</li> </li>
<li class="tab col s3"><a href="#notify"><i class="material-icons">announcement</i> {%trans "Notifications" %}</a> <li class="tab col s3"><a href="#notify"><i class="material-icons">announcement</i> {%trans "Notifications" %}</a>
</li> </li>
@ -47,6 +47,11 @@
</li> </li>
</ul> </ul>
</li> </li>
<li>
{% blocktrans %}
Use the <strong><i class="material-icons">web</i> Review</strong> section to review what was parsed/detected from your defined configuration.
{% endblocktrans %}
</li>
<li> <li>
{% blocktrans %} {% blocktrans %}
Use the <strong><i class="material-icons">announcement</i> Notifications</strong> section to test out your saved configuration. Use the <strong><i class="material-icons">announcement</i> Notifications</strong> section to test out your saved configuration.
@ -54,15 +59,6 @@
</li> </li>
</ol> </ol>
</div> </div>
<div class="section no-config">
<div class="divider"></div>
<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>
<div class="divider"></div>
</div>
{% else %} {% else %}
<div class="section"> <div class="section">
<h5>{% trans "Apprise Configuration is Locked" %}</h5> <h5>{% trans "Apprise Configuration is Locked" %}</h5>
@ -147,11 +143,18 @@
<div id="review" class="col s12"> <div id="review" class="col s12">
{% if not CONFIG_LOCK %} {% if not CONFIG_LOCK %}
<p> <div class="section no-config">
{% blocktrans %}The following URLs have been detected:{% endblocktrans %} <div class="divider"></div>
</p> <p>
<div class="section"> <i class="material-icons info">info</i>
{% blocktrans %}Once you have successfully loaded <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>
<div class="divider"></div>
</div>
<div class="section has-config">
<h5>{% trans "Loaded Configuration" %}</h5> <h5>{% trans "Loaded Configuration" %}</h5>
<p>{% blocktrans %}<strong>Tip:</strong> Click on a tag (🏷️) to pre-select in the <strong><i class="material-icons">announcement</i>Notifications</strong> section with the tag already pre-selected.{% endblocktrans %}</p>
<div id="url-list"></div> <div id="url-list"></div>
<div id="url-list-progress" class="progress" style="width:70%"> <div id="url-list-progress" class="progress" style="width:70%">
<div class="indeterminate"></div> <div class="indeterminate"></div>
@ -189,24 +192,35 @@
{% if STATEFUL_MODE != 'disabled' %} {% if STATEFUL_MODE != 'disabled' %}
async function main_init(){ async function main_init(){
const params = new Proxy(new URLSearchParams(window.location.search), {
get: (searchParams, prop) => searchParams.get(prop),
});
if (params.title) {
document.querySelector('#id_title').value = params.title;
}
if (params.body) {
document.querySelector('#id_body').value = params.body;
}
{% if not CONFIG_LOCK %}
// disable the notification tab until we know for certain // disable the notification tab until we know for certain
// a notification is possible // a notification is possible
document.querySelector('.config-overview li a[href="#notify"]') document.querySelector('.config-overview li a[href="#notify"]')
.parentNode.classList.add('disabled'); .parentNode.classList.add('disabled');
// Disable any has-config entries // Disable any has-config entries
document.querySelector('.has-config') document.querySelectorAll('.has-config').forEach(function(e){
.style.display = 'none'; e.style.display = 'none'
});
// Ensure we show our progress loader and reset our url list // Ensure we show our progress loader and reset our url list
document.querySelector('#url-list').textContent = '' document.querySelector('#url-list').textContent = ''
document.querySelector('#url-list-progress').style.display = null; document.querySelector('#url-list-progress').style.display = null;
{% if not CONFIG_LOCK %}
// Ensure no-config sections are visible // Ensure no-config sections are visible
document.querySelector('.no-config') document.querySelectorAll('.no-config').forEach(function(e){
.style.display = null; e.style.display = null;
{% endif %} });
// perform a tag retrieval; start with 'all' // perform a tag retrieval; start with 'all'
let tags = ['all']; let tags = ['all'];
@ -217,7 +231,7 @@ async function main_init(){
if(jsonResponse.status == 204) { if(jsonResponse.status == 204) {
// Take an early exit // Take an early exit
document.querySelector('#url-list-progress').style.display = 'none'; document.querySelector('#url-list-progress').style.display = 'none';
document.querySelector('#url-list').textContent = '{% trans "There are no URLs defined. Click on the ⚙️ Configuration tab and define some." %}' document.querySelector('#url-list').textContent = ''
return; return;
} else if(jsonResponse.status != 200) { } else if(jsonResponse.status != 200) {
@ -234,42 +248,71 @@ async function main_init(){
const external_data = tags.concat(data.tags).reduce(function(result, item) { const external_data = tags.concat(data.tags).reduce(function(result, item) {
result[item] = null; result[item] = null;
return result; return result;
}, {}) }, {})
const chipElement = document.querySelector('.chips'); const chipElement = document.querySelector('.chips');
M.Chips.init(chipElement, { M.Chips.init(chipElement, {
placeholder: 'Optional Tag', placeholder: '{% trans "Optional Tag" %}',
secondaryPlaceholder: 'Another Tag', secondaryPlaceholder: '{% trans "Another Tag" %}',
autocompleteOptions: { autocompleteOptions: {
data: external_data, data: external_data,
minLength: 0 minLength: 0
}, },
onChipAdd: function(e, chip) { onChipAdd: function(e, data) {
var $this = this; var $this = this;
const chip = data.childNodes[0].textContent;
document.querySelectorAll(`#url-list .chip[name=${chip}]`).forEach(function(e){
if (!e.classList.contains('selected')) {
e.classList.add('selected');
}
})
document.querySelectorAll(`#url-list .chip.chip-notag`).forEach(function(e){
if (e.classList.contains('selected')) {
e.classList.remove('selected');
}
})
$this.chipsData.forEach(function(e, index) { $this.chipsData.forEach(function(e, index) {
if(!(e.tag in external_data)) if(!(e.tag in external_data))
$this.deleteChip(index); $this.deleteChip(index);
}) })
},
onChipDelete: function(e, data) {
var $this = this;
const chip = data.childNodes[0].textContent;
document.querySelectorAll(`#url-list .chip[name=${chip}]`).forEach(function(e){
if (e.classList.contains('selected')) {
e.classList.remove('selected');
}
})
if ($this.chipsData.length == 0){
// last item
document.querySelectorAll(`#url-list .chip.chip-notag`).forEach(function(e){
if (!e.classList.contains('selected')) {
e.classList.add('selected');
}
})
}
} }
}); });
{% else %}
// our GET parameters to be treated as template values {# Empty external data set #}
var tagRe = new RegExp('[^[A-Za-z0-9_-]+'); const data = {
const params = new Proxy(new URLSearchParams(window.location.search), { urls: []
get: (searchParams, prop) => searchParams.get(prop), };
M.Chips.init(chipElement, {
placeholder: '{% trans "Optional Tag" %}',
secondaryPlaceholder: '{% trans "Another Tag" %}'
}); });
{% endif %}
const chipInstance = M.Chips.getInstance(chipElement);
if (params.tag) { if (params.tag) {
// our GET parameters to be treated as template values
var tagRe = new RegExp('[^[A-Za-z0-9_-]+');
params.tag.split(tagRe).forEach(function (tag, index) { params.tag.split(tagRe).forEach(function (tag, index) {
M.Chips.getInstance(chipElement).addChip({tag: tag, image: ''}); chipInstance.addChip({tag: tag, image: ''});
}); });
} }
if (params.title) { {% if not CONFIG_LOCK %}
document.querySelector('#id_title').value = params.title;
}
if (params.body) {
document.querySelector('#id_body').value = params.body;
}
// Now build our our loaded list of configuration for our welcome page // Now build our our loaded list of configuration for our welcome page
let urlList = document.createElement('ul'); let urlList = document.createElement('ul');
@ -281,51 +324,86 @@ async function main_init(){
li.setAttribute('class', 'card-panel'); li.setAttribute('class', 'card-panel');
li.appendChild(code); li.appendChild(code);
urlList.appendChild(li);
// Store `all` tag
entry.tags.unshift('all')
if (entry.tags.length === 1){
// This entry triggers when no tags are defined
// Store '' (empty) tag for notice generation
entry.tags.unshift('')
}
// Get our tags associate with the URL // Get our tags associate with the URL
entry.tags.forEach(function (tag) { entry.tags.forEach(function (tag) {
let chip = document.createElement('div'); let chip = document.createElement('div');
chip.setAttribute('class', 'chip'); chip.setAttribute('class', `chip`);
chip.setAttribute('name', tag); if(tag.length > 0) {
chip.setAttribute('href', `?tag=${tag}#notify`); // we're dealing with a valid tag
chip.textContent = `🏷️ ${tag}`; chip.setAttribute('name', tag);
li.appendChild(chip); chip.textContent = `🏷️ ${tag}`;
chip.addEventListener('click', function(e) { const index = chipInstance.chipsData.findIndex(function (e) {
e.preventDefault(); return e.tag === tag;})
window.history.pushState(null, null, this.getAttribute('href')); if (index >= 0) {
document.querySelector('.config-overview li a[href="#notify"]').click() chip.classList.add('selected');
}
li.appendChild(chip);
const chipElement = document.querySelector('.chips'); chip.addEventListener('click', function(e) {
M.Chips.getInstance(chipElement).addChip({tag: this.getAttribute('name'), image: ''}); e.preventDefault();
}, false); const index = chipInstance.chipsData.findIndex(function (e) {
return e.tag === tag;
});
if(index < 0) {
chipInstance.addChip({tag: this.getAttribute('name'), image: ''});
} else {
chipInstance.deleteChip(index);
}
}, false);
} else {
// no tags were defined for this element
chip.classList.add('chip-notag');
chip.textContent = '🔖 ' + 'no-tag';
if (chipInstance.chipsData.length === 0) {
chip.classList.add('selected');
}
li.appendChild(chip);
chip.addEventListener('click', function(e) {
e.preventDefault();
while(chipInstance.chipsData.length > 0){
chipInstance.deleteChip(0);
}
chip.classList.add('selected');
}, false);
}
}); });
urlList.appendChild(li);
}); });
{% endif %}
{% if not CONFIG_LOCK %}
// Store our new list // Store our new list
document.querySelector('#url-list-progress').style.display = 'none'; document.querySelector('#url-list-progress').style.display = 'none';
document.querySelector('#url-list').textContent = '' document.querySelector('#url-list').textContent = ''
if(urlList.childNodes.length > 0) { if(urlList.childNodes.length > 0) {
// Ensure has-config sections are visible // Ensure has-config sections are visible
document.querySelector('.has-config') document.querySelectorAll('.has-config').forEach(function(e){
.style.display = null; e.style.display = null;
});
// Remove our restrictions on sending notifications // Remove our restrictions on sending notifications
document.querySelector('.config-overview li a[href="#notify"]') document.querySelector('.config-overview li a[href="#notify"]')
.parentNode.classList.remove('disabled'); .parentNode.classList.remove('disabled');
{% if not CONFIG_LOCK %}
// Disable any no-config entries // Disable any no-config entries
document.querySelector('.no-config') document.querySelectorAll('.no-config').forEach(function(e){
.style.display = 'none'; e.style.display = 'none';
{% endif %} });
// Save our list to the screen // Save our list to the screen
document.querySelector('#url-list').appendChild(urlList); document.querySelector('#url-list').appendChild(urlList);
{% if not CONFIG_LOCK %}
// //
// Load our configuration now into the configuration tab // Load our configuration now into the configuration tab
// //
@ -362,14 +440,15 @@ async function main_init(){
} }
document.querySelector('#id_format').dispatchEvent(event); document.querySelector('#id_format').dispatchEvent(event);
} }
{% endif %}
} else { } else {
document.querySelector('#url-list').textContent = '{% trans "There are no Apprise URL(s) loaded." %}' document.querySelector('#url-list').textContent = '{% trans "There are no Apprise URL(s) loaded." %}'
} }
{% endif %}
return null; return null;
} }
{% if not CONFIG_LOCK %}
function config_init() { function config_init() {
// over-ride manual submit for a nicer user experience // over-ride manual submit for a nicer user experience
document.querySelector('#addconfig').onsubmit = function(event) { document.querySelector('#addconfig').onsubmit = function(event) {
@ -443,6 +522,7 @@ function config_init() {
return false; return false;
} }
} }
{% endif %}
function form_file_input_hack() { function form_file_input_hack() {
/* /*
@ -478,7 +558,8 @@ function form_file_input_hack() {
selected.textContent = file.name; selected.textContent = file.name;
}); });
}); });
} }
function notify_init() { function notify_init() {
// over-ride manual submit for a nicer user experience // over-ride manual submit for a nicer user experience
document.querySelector('#donotify').onsubmit = function(event) { document.querySelector('#donotify').onsubmit = function(event) {
@ -571,16 +652,6 @@ function notify_init() {
return false; return false;
} }
} }
/* Initialize our page */
main_init();
{% if not CONFIG_LOCK %}
/* Initialze our configuration */
config_init();
{% endif %}
notify_init();
form_file_input_hack();
{% endif %} {% endif %}
{% endblock %} {% endblock %}
@ -599,5 +670,14 @@ document.querySelector('label [for="id_tag"]')
// Hide tag field since we use the pretty Materialize Chip setup instead // Hide tag field since we use the pretty Materialize Chip setup instead
document.querySelector('#id_tag').style.display = 'none'; document.querySelector('#id_tag').style.display = 'none';
/* Initialize our page */
main_init();
{% if not CONFIG_LOCK %}
/* Initialze our configuration */
config_init();
{% endif %}
notify_init();
form_file_input_hack();
{% endif %} {% endif %}
{% endblock %} {% endblock %}

View File

@ -125,10 +125,11 @@ textarea {
float: left; float: left;
} }
#url-list .chip { .chip {
margin: 0.3rem; margin: 0.3rem;
background-color: inherit; background-color: inherit;
border: 1px solid #e4e4e4; border: 1px solid #464646;
color: #464646;
cursor: pointer; cursor: pointer;
} }
@ -232,3 +233,7 @@ code.config-id {
padding: 0 1em; padding: 0 1em;
overflow: hidden; overflow: hidden;
} }
.chip.selected {
font-weight: 600;
}

View File

@ -1324,3 +1324,8 @@ input[type=range]::-ms-thumb {
color: #ebcb8b; color: #ebcb8b;
background-color: #2e3440; background-color: #2e3440;
} }
.chip.selected {
color: #fff;
background-color: #258528!important;
}

View File

@ -1,7 +1,21 @@
.tabs .tab a {background-color: #f3f3f3;} .tabs .tab a {background-color: #f3f3f3;}
.tabs.tabs-transparent .tab a,.tabs.tabs-transparent .tab.disabled a,.tabs.tabs-transparent .tab.disabled a:hover, .tab.disabled i.material-icons{color:#a7a7a7} .tabs.tabs-transparent .tab a,
.tabs .tab.disabled a,.tabs .tab.disabled a:hover{background-color: #f3f3f3; color:#a7a7a7} .tabs.tabs-transparent .tab.disabled a,
.tabs.tabs-transparent .tab.disabled a:hover,
.tab.disabled i.material-icons{
color:#a7a7a7
}
.tabs .tab.disabled a,
.tabs .tab.disabled a:hover {
background-color: #f3f3f3;
color:#a7a7a7
}
.file-selected { .file-selected {
color: #039be5; color: #039be5;
background-color: #f3f3f3; background-color: #f3f3f3;
} }
.chip.selected {
color: #fff;
background-color: #258528!important;
}