Skip to content

Commit

Permalink
Improved tagging visuals (#181)
Browse files Browse the repository at this point in the history
  • Loading branch information
caronc authored Apr 2, 2024
1 parent 8aba73f commit 515cadf
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 24 deletions.
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ There is a small built-in *Configuration Manager* that can be optionally accesse
Below is a screenshot of how you can assign your Apprise URLs to your `{KEY}`. You can define both TEXT or YAML [Apprise configurations](https://github.com/caronc/apprise/wiki/config).<br/>
![Screenshot of GUI - Configuration](https://raw.githubusercontent.com/caronc/apprise-api/master/Screenshot-2.png)

Below is a screenshot of the review tab where you can preview what Apprise URL(s) got loaded from your defined configuration. It also allows you to view the tags associated with them (if any).<br/>
Below is a screenshot of the review tab where you can preview what Apprise URL(s) got loaded from your defined configuration. It also allows you to view the tags associated with them (if any). Should you chose to send a test notification via this API, you can select the tags in advance you wish to target from here.<br/>
![Screenshot of GUI - Review](https://raw.githubusercontent.com/caronc/apprise-api/master/Screenshot-3.png)

Once you've saved your configuration, you'll be able to use the *Notification* tab to send your messages to one or more of the services you defined in your configuration. You can use the tag `all` to notify all of your services regardless of what tag had otherwise been assigned to them.<br/>
With configuration in place, you'll be able to use the *Notification* tab to send a test message to one or more of the services you defined in your configuration. You can also select from the tags (if any) you pre-assigned to your URLs defined. If you did not define any tags with you configured URLs, then you do not need to identify any here. You can use the tag `all` to notify all of your services regardless of what tag had otherwise been assigned to them (if any at all).<br/>
![Screenshot of GUI - Notifications](https://raw.githubusercontent.com/caronc/apprise-api/master/Screenshot-4.png)

At the end of the day, the GUI just simply offers a user friendly interface to the same API developers can directly interface with if they wish to.
Expand Down Expand Up @@ -72,7 +72,7 @@ docker build -t apprise/local:latest -f Dockerfile .
docker run --name apprise \
-p 8000:8000 \
-e APPRISE_WORKER_COUNT=1 \
-d apprise/local:latest
-d apprise/local:latest
```
A `docker-compose.yml` file is already set up to grant you an instant production ready simulated environment:

Expand Down Expand Up @@ -142,7 +142,7 @@ Here is a *stateless* example of how one might send a notification (using `/noti
curl -X POST -d 'urls=mailto://user:[email protected]&body=test message' \
http://localhost:8000/notify

# Send a notification with an attachment
# Send a notification with an attachment:
curl -X POST \
-F 'urls=mailto://user:[email protected]' \
-F 'body=test message' \
Expand Down Expand Up @@ -272,7 +272,7 @@ curl -X POST \
http://localhost:8000/notify/abc123
```

🏷️ You can also leverage *tagging* which allows you to associate one or more tags with your Apprise URLs. By doing this, notifications only need to be referred to by their easy to remember notify tag name such as `devops`, `admin`, `family`, etc. You can very easily group more than one notification service under the same *tag* allowing you to notify a group of services at once. This is accomplished through configuration files ([documented here](https://github.com/caronc/apprise/wiki/config)) that can be saved to the persistent storage previously associated with a `{KEY}`.
🏷️ Leveraging *tagging* allows you to associate one or more tags (or categories) with your Apprise URLs. By doing this, notifications only need to be referred to by their easy to remember notify tag name such as `devops`, `admin`, `family`, etc. You can very easily group more than one notification service under the same *tag* allowing you to notify a group of services at once. This is accomplished through configuration files ([documented here](https://github.com/caronc/apprise/wiki/config)) that can be saved to the persistent storage previously associated with a `{KEY}`.

```bash
# Send notification(s) to a {KEY} defined as 'abc123'
Expand All @@ -288,7 +288,7 @@ curl -X POST -d '{"tag":"devops", "body":"test message"}' \

### Tagging

Leveraging tagging is one of the things that makes Apprise great. Not only can you group one or more notifications together (all sharing the same tag), but you can assign multiple tags to the same URL and trigger it through crafted and selected tag expressions.
Tagging is one of the things that makes Apprise super handy and easy to use. Not only can you group one or more notifications together (all sharing the same tag), but you can assign multiple tags to the same URL and trigger it through crafted and selected tag expressions.

| Example | Effect |
| --------------------- | ------------------------------ |
Expand Down Expand Up @@ -369,7 +369,7 @@ The use of environment variables allow you to provide over-rides to default sett
| `APPRISE_RECURSION_MAX` | This defines the number of times one Apprise API Server can (recursively) call another. This is to both support and mitigate abuse through [the `apprise://` schema](https://github.com/caronc/apprise/wiki/Notify_apprise_api) for those who choose to use it. When leveraged properly, you can increase this (recursion max) value and successfully load balance the handling of many notification requests through many additional API Servers. By default this value is set to `1` (one).
| `APPRISE_WEBHOOK_URL` | Define a Webhook that Apprise should `POST` results to upon each notification call made. This must be in the format of an `http://` or `https://` URI. By default no URL is specified and no webhook is actioned.
| `APPRISE_WORKER_COUNT` | Over-ride the number of workers to run. by default this is calculated `(2 * CPUS_DETECTED) + 1` [as advised by Gunicorn's website](https://docs.gunicorn.org/en/stable/design.html#how-many-workers). Hobby enthusiasts and/or users who are simply setting up Apprise to support their home (light-weight usage) may wish to set this value to `1` to limit the resources the Apprise server prepares for itself.
| `APPRISE_WORKER_TIMEOUT` | Over-ride the worker timeout value; by default this is `300` (5 min) which should be more than enough time to send all pending notifications.
| `APPRISE_WORKER_TIMEOUT` | Over-ride the worker timeout value (in seconds); by default this is `300` (5 min) which should be more than enough time to send all pending notifications.
| `BASE_URL` | Those who are hosting the API behind a proxy that requires a subpath to gain access to this API should specify this path here as well. By default this is not set at all.
| `LOG_LEVEL` | Adjust the log level to the console. Possible values are `CRITICAL`, `ERROR`, `WARNING`, `INFO`, and `DEBUG`.
| `DEBUG` | This defaults to `no` and can however be set to `yes` by simply defining the global variable as such.
Expand Down Expand Up @@ -469,10 +469,10 @@ devteam=apprise://localhost:8000/{KEY}?tags=devteam
# the only catch is you need to map your tags on the local server to the tags
# you want to pass upstream to your Apprise server using this method.
# In the above we tied the local keyword `friends` to the apprise server using the tag `friends`
# In the above we tied the local keyword `devteam` to the apprise server using the tag `devteam`
```

We could trigger our notification to our friends now like:
We could trigger our notification to our devteam now like:

```bash
# Trigger our service:
Expand Down
68 changes: 53 additions & 15 deletions apprise_api/api/templates/config.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ <h4>{% trans "Management for Config ID:" %} <code class="config-id">{{ key }}</c
</li>
<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 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" %} <span class="card-count"></span></a>
</li>
</ul>
</div>
Expand Down Expand Up @@ -190,6 +190,13 @@ <h4>{% trans "Persistent Store Endpoints" %}</h4>
{% block jsfooter %}

{% if STATEFUL_MODE != 'disabled' %}
function update_count() {
const p_count = document.querySelectorAll('#url-list li.card-panel.selected').length;
document.querySelectorAll(".card-count").forEach(function(e){
e.textContent = `(${p_count})`;
})
}

async function main_init(){

const params = new Proxy(new URLSearchParams(window.location.search), {
Expand Down Expand Up @@ -263,35 +270,57 @@ <h4>{% trans "Persistent Store Endpoints" %}</h4>
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');
}
e.classList.add('selected');
const p = e.parentNode;
if (!p.classList.contains('selected')) {
p.classList.add('selected');
}
}
})
document.querySelectorAll(`#url-list .chip.chip-notag`).forEach(function(e){
if (e.classList.contains('selected')) {
e.classList.remove('selected');
const p = e.parentNode;
if (!p.querySelector('.selected')) {
if (p.classList.contains('selected')) {
p.classList.remove('selected');
}
}
}
})
$this.chipsData.forEach(function(e, index) {
if(!(e.tag in external_data))
$this.deleteChip(index);
})
update_count();
},
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 (e.classList.contains('selected')) {
e.classList.remove('selected');
}
const p = e.parentNode;
if (!p.querySelector('.selected')) {
if (p.classList.contains('selected')) {
p.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');
}
const p = e.parentNode;
if (!p.classList.contains('selected')) {
p.classList.add('selected');
}
})
}
update_count();
}
});
{% else %}
Expand Down Expand Up @@ -332,8 +361,8 @@ <h4>{% trans "Persistent Store Endpoints" %}</h4>
// This entry triggers when no tags are defined
// Store '' (empty) tag for notice generation
entry.tags.unshift('')

}

// Get our tags associate with the URL
entry.tags.forEach(function (tag) {
let chip = document.createElement('div');
Expand All @@ -347,6 +376,7 @@ <h4>{% trans "Persistent Store Endpoints" %}</h4>
return e.tag === tag;})
if (index >= 0) {
chip.classList.add('selected');
li.classList.add('selected');
}
li.appendChild(chip);

Expand All @@ -364,18 +394,26 @@ <h4>{% trans "Persistent Store Endpoints" %}</h4>
} else {
// no tags were defined for this element
chip.classList.add('chip-notag');
chip.textContent = '🔖 ' + 'no-tag';
chip.textContent = '🔖 no-tag';
if (chipInstance.chipsData.length === 0) {
chip.classList.add('selected');
if (!li.classList.contains('selected')) {
li.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);
e.preventDefault();
while(chipInstance.chipsData.length > 0){
chipInstance.deleteChip(0);
}
chip.classList.add('selected');
if (!li.classList.contains('selected')) {
li.classList.add('selected');
}
update_count();
});
}
});
});
Expand Down Expand Up @@ -444,7 +482,7 @@ <h4>{% trans "Persistent Store Endpoints" %}</h4>
document.querySelector('#url-list').textContent = '{% trans "There are no Apprise URL(s) loaded." %}'
}
{% endif %}

update_count();
return null;
}

Expand Down
1 change: 1 addition & 0 deletions apprise_api/static/css/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ textarea {
border-radius: 12px;
width: 50%;
min-width: 35rem;
min-height: 12em;
float: left;
}

Expand Down
4 changes: 4 additions & 0 deletions apprise_api/static/css/theme-dark.min.css
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,10 @@ em {
background-color: #fff
}

#url-list .card-panel.selected {
background-color: #a0c8ef;
}

.chip {
color: #d8dee9;
background-color: #2e3440 !important;
Expand Down
8 changes: 8 additions & 0 deletions apprise_api/static/css/theme-light.min.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@
background-color: #f3f3f3;
}

#url-list .card-panel.selected {
background-color: #fff8dc;
}

.chip {
background-color: #fff!important;
}

.chip.selected {
color: #fff;
background-color: #258528!important;
Expand Down

0 comments on commit 515cadf

Please sign in to comment.