0
0
Fork 0
mirror of https://github.com/healthchecks/healthchecks.git synced 2025-04-07 22:25:35 +00:00

Improve channel rendering in the group form

* Use the custom-styled checkbox
* Use PNG instead of icon font for channel kind logos
* Show channel's description the same way as in the channels list
  (using a reusable template, templates/front/channel_description.html)
This commit is contained in:
Pēteris Caune 2023-10-12 14:37:00 +03:00
parent 7b03e1f95b
commit 37caa94ff5
No known key found for this signature in database
GPG key ID: E28D7679E9A9EDE2
7 changed files with 141 additions and 112 deletions

View file

@ -10,10 +10,7 @@ from urllib.parse import quote, urlencode
from django import forms from django import forms
from django.conf import settings from django.conf import settings
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from hc.api.models import Channel
from hc.front.validators import ( from hc.front.validators import (
CronExpressionValidator, CronExpressionValidator,
TimezoneValidator, TimezoneValidator,
@ -344,16 +341,12 @@ class GroupForm(forms.Form):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields["channels"].choices = ( self.fields["channels"].choices = (
( (c.code, c) for c in project.channel_set.exclude(kind="group")
c.code,
format_html('<span class="ic-{}"></span> {}', mark_safe(c.kind), c),
)
for c in Channel.objects.filter(project=project).exclude(kind="group")
) )
error_css_class = "has-error" error_css_class = "has-error"
label = forms.CharField(max_length=100, required=False) label = forms.CharField(max_length=100, required=False)
channels = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple) channels = forms.MultipleChoiceField()
def get_value(self) -> str: def get_value(self) -> str:
return ",".join(self.cleaned_data["channels"]) return ",".join(self.cleaned_data["channels"])

View file

@ -249,23 +249,3 @@ img.kind-ntfy {
filter: drop-shadow(1px 1px 1px rgba(0,0,0,0.2)); filter: drop-shadow(1px 1px 1px rgba(0,0,0,0.2));
} }
#id_channels > div:nth-child(n+2) {
border-top: 1px solid var(--border-color);
}
#id_channels > div > label {
margin: 8px;
display: flex;
align-items: center;
gap: 8px;
font-weight: normal;
}
label[for^="id_channels"] {
cursor: pointer;
}
#id_channels input {
position: relative;
top: -1px;
}

27
static/css/group_form.css Normal file
View file

@ -0,0 +1,27 @@
#channel-choices label {
display: block;
padding: 12px 12px 12px 32px;
margin: 0;
font-weight: normal;
display: flex;
gap: 12px;
cursor: pointer;
user-select: none;
}
#channel-choices label:nth-child(n + 2) {
border-top: 1px solid var(--border-color);
}
#channel-choices .checkmark {
top: 20px;
}
#channel-choices img {
max-height: 40px;
}
#channel-choices .channel-details-mini {
font-size: 11.7px;
color: #888;
}

View file

@ -38,6 +38,7 @@
<link rel="stylesheet" href="{% static 'css/details.css' %}" type="text/css"> <link rel="stylesheet" href="{% static 'css/details.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/docs.css' %}" type="text/css"> <link rel="stylesheet" href="{% static 'css/docs.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/docs_cron.css' %}" type="text/css"> <link rel="stylesheet" href="{% static 'css/docs_cron.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/group_form.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/icomoon.css' %}" type="text/css"> <link rel="stylesheet" href="{% static 'css/icomoon.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/log.css' %}" type="text/css"> <link rel="stylesheet" href="{% static 'css/log.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/login.css' %}" type="text/css"> <link rel="stylesheet" href="{% static 'css/login.css' %}" type="text/css">

View file

@ -0,0 +1,77 @@
{% if ch.kind == "email" %}
Email to <span>{{ ch.email.value }}</span>
{% if ch.email.notify_down and not ch.email.notify_up %}
(down only)
{% endif %}
{% if ch.email.notify_up and not ch.email.notify_down %}
(up only)
{% endif %}
{% elif ch.kind == "pd" %}
PagerDuty account <span>{{ ch.pd.account }}</span>
{% elif ch.kind == "po" %}
Pushover ({{ ch.po_priority }} priority)
{% elif ch.kind == "slack" %}
Slack
{% if ch.slack_team %}
team <span>{{ ch.slack_team }}</span>,
channel <span>{{ ch.slack_channel }}</span>
{% endif %}
{% elif ch.kind == "telegram" %}
Telegram
{% if ch.telegram.type == "group" %}
group <span>{{ ch.telegram.name }}</span>
{% elif ch.telegram.type == "private" %}
user <span>{{ ch.telegram.name }}</span>
{% elif ch.telegram.type == "channel" %}
channel <span>{{ ch.telegram.name }}</span>
{% endif %}
{% elif ch.kind == "sms" %}
SMS to <span>{{ ch.phone.value }}</span>
{% if ch.phone.notify_down and not ch.phone.notify_up %}
(down only)
{% endif %}
{% if ch.phone.notify_up and not ch.phone.notify_down %}
(up only)
{% endif %}
{% elif ch.kind == "call" %}
Phone call to <span>{{ ch.phone.value }}</span>
{% elif ch.kind == "trello" %}
Trello
board <span>{{ ch.trello_board_list|first }}</span>,
list <span>{{ ch.trello_board_list|last }}</span>
{% elif ch.kind == "matrix" %}
Matrix <span>{{ ch.value }}</span>
{% elif ch.kind == "whatsapp" %}
WhatsApp to <span>{{ ch.phone.value }}</span>
{% if ch.phone.notify_down and not ch.phone.notify_up %}
(down only)
{% endif %}
{% if ch.phone.notify_up and not ch.phone.notify_down %}
(up only)
{% endif %}
{% elif ch.kind == "zulip" %}
Zulip
{% if ch.zulip_type == "stream" %}
stream <span>{{ ch.zulip_to}}</span>
{% elif ch.zulip_type == "private" %}
user <span>{{ ch.zulip_to}}</span>
{% endif %}
{% elif ch.kind == "signal" %}
Signal to <span>{{ ch.phone.value }}</span>
{% if ch.phone.notify_down and not ch.phone.notify_up %}
(down only)
{% endif %}
{% if ch.phone.notify_up and not ch.phone.notify_down %}
(up only)
{% endif %}
{% elif ch.kind == "ntfy" %}
ntfy topic <span>{{ ch.ntfy_topic }}</span>,
{{ ch.ntfy_priority_display }} priority
{% elif ch.kind == "group" %}
Group,
{% with ch.group_channels|length as num_members %}
{{ num_members }} member{{ num_members|pluralize}}
{% endwith %}
{% else %}
{{ ch.get_kind_display }}
{% endif %}

View file

@ -32,85 +32,14 @@
</td> </td>
<td> <td>
<div class="edit-name" data-toggle="modal" data-target="#name-{{ ch.code }}"> <div class="edit-name" data-toggle="modal" data-target="#name-{{ ch.code }}">
{% if ch.name %} {% if ch.name %}
{{ ch.name }} {{ ch.name }}
{% else %} {% else %}
<div class="unnamed">unnamed</div> <div class="unnamed">unnamed</div>
{% endif %} {% endif %}
<div class="channel-details-mini"> <div class="channel-details-mini">
{% if ch.kind == "email" %} {% include "front/channel_description.html" with ch=ch %}
Email to <span>{{ ch.email.value }}</span> </div>
{% if ch.email.notify_down and not ch.email.notify_up %}
(down only)
{% endif %}
{% if ch.email.notify_up and not ch.email.notify_down %}
(up only)
{% endif %}
{% elif ch.kind == "pd" %}
PagerDuty account <span>{{ ch.pd.account }}</span>
{% elif ch.kind == "po" %}
Pushover ({{ ch.po_priority }} priority)
{% elif ch.kind == "slack" %}
Slack
{% if ch.slack_team %}
team <span>{{ ch.slack_team }}</span>,
channel <span>{{ ch.slack_channel }}</span>
{% endif %}
{% elif ch.kind == "telegram" %}
Telegram
{% if ch.telegram.type == "group" %}
group <span>{{ ch.telegram.name }}</span>
{% elif ch.telegram.type == "private" %}
user <span>{{ ch.telegram.name }}</span>
{% elif ch.telegram.type == "channel" %}
channel <span>{{ ch.telegram.name }}</span>
{% endif %}
{% elif ch.kind == "sms" %}
SMS to <span>{{ ch.phone.value }}</span>
{% if ch.phone.notify_down and not ch.phone.notify_up %}
(down only)
{% endif %}
{% if ch.phone.notify_up and not ch.phone.notify_down %}
(up only)
{% endif %}
{% elif ch.kind == "call" %}
Phone call to <span>{{ ch.phone.value }}</span>
{% elif ch.kind == "trello" %}
Trello
board <span>{{ ch.trello_board_list|first }}</span>,
list <span>{{ ch.trello_board_list|last }}</span>
{% elif ch.kind == "matrix" %}
Matrix <span>{{ ch.value }}</span>
{% elif ch.kind == "whatsapp" %}
WhatsApp to <span>{{ ch.phone.value }}</span>
{% if ch.phone.notify_down and not ch.phone.notify_up %}
(down only)
{% endif %}
{% if ch.phone.notify_up and not ch.phone.notify_down %}
(up only)
{% endif %}
{% elif ch.kind == "zulip" %}
Zulip
{% if ch.zulip_type == "stream" %}
stream <span>{{ ch.zulip_to}}</span>
{% elif ch.zulip_type == "private" %}
user <span>{{ ch.zulip_to}}</span>
{% endif %}
{% elif ch.kind == "signal" %}
Signal to <span>{{ ch.phone.value }}</span>
{% if ch.phone.notify_down and not ch.phone.notify_up %}
(down only)
{% endif %}
{% if ch.phone.notify_up and not ch.phone.notify_down %}
(up only)
{% endif %}
{% elif ch.kind == "ntfy" %}
ntfy topic <span>{{ ch.ntfy_topic }}</span>,
{{ ch.ntfy_priority_display }} priority
{% else %}
{{ ch.get_kind_display }}
{% endif %}
</div>
</div> </div>
</td> </td>
<td> <td>

View file

@ -40,18 +40,40 @@
</div> </div>
<div class="form-group {{ form.channels.css_classes }}"> <div class="form-group {{ form.channels.css_classes }}">
<label for="channels" class="col-sm-2 control-label">Integrations</label> <label for="channels" class="col-sm-2 control-label">Integrations</label>
<div class="col-sm-6"> <div id="channel-choices" class="col-sm-6">
{{ form.channels }} {% for code, ch in form.channels.field.choices %}
<label class="checkbox-container">
<input
type="checkbox"
name="channels"
value="{{ code }}"
{% if code in form.channels.value %}checked{% endif %}>
<span class="checkmark"></span>
<img src="{% static ch.icon_path %}" alt="{{ ch.get_kind_display }}" class="kind-{{ ch.kind }}" />
<div class="name-desc">
{% if ch.name %}
{{ ch.name }}
{% else %}
<div class="unnamed">unnamed</div>
{% endif %}
<div class="channel-details-mini">
{% include "front/channel_description.html" with ch=ch %}
</div>
</div>
</label>
{% endfor %}
{% if form.channels.errors %} {% if form.channels.errors %}
<div class="help-block">{{ form.channels.errors|join:"" }}</div> <div class="help-block">
{{ form.channels.errors|join:"" }}
</div>
{% endif %} {% endif %}
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">Save Integration</button> <button type="submit" class="btn btn-primary">Save Group</button>
</div> </div>
</div> </div>
</form> </form>