From 37caa94ff5ae0db1abacc206ebfc808f73262816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C4=93teris=20Caune?= <cuu508@gmail.com> Date: Thu, 12 Oct 2023 14:37:00 +0300 Subject: [PATCH] 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) --- hc/front/forms.py | 11 +-- static/css/channels.css | 20 ------ static/css/group_form.css | 27 ++++++++ templates/base.html | 1 + templates/front/channel_description.html | 77 +++++++++++++++++++++ templates/front/channels.html | 87 +++--------------------- templates/integrations/group_form.html | 30 ++++++-- 7 files changed, 141 insertions(+), 112 deletions(-) create mode 100644 static/css/group_form.css create mode 100644 templates/front/channel_description.html diff --git a/hc/front/forms.py b/hc/front/forms.py index 6f1c081f..e88ad183 100644 --- a/hc/front/forms.py +++ b/hc/front/forms.py @@ -10,10 +10,7 @@ from urllib.parse import quote, urlencode from django import forms from django.conf import settings 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 ( CronExpressionValidator, TimezoneValidator, @@ -344,16 +341,12 @@ class GroupForm(forms.Form): super().__init__(*args, **kwargs) self.fields["channels"].choices = ( - ( - c.code, - format_html('<span class="ic-{}"></span> {}', mark_safe(c.kind), c), - ) - for c in Channel.objects.filter(project=project).exclude(kind="group") + (c.code, c) for c in project.channel_set.exclude(kind="group") ) error_css_class = "has-error" label = forms.CharField(max_length=100, required=False) - channels = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple) + channels = forms.MultipleChoiceField() def get_value(self) -> str: return ",".join(self.cleaned_data["channels"]) diff --git a/static/css/channels.css b/static/css/channels.css index b8cea965..5a3d6910 100644 --- a/static/css/channels.css +++ b/static/css/channels.css @@ -249,23 +249,3 @@ img.kind-ntfy { 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; -} \ No newline at end of file diff --git a/static/css/group_form.css b/static/css/group_form.css new file mode 100644 index 00000000..cd4bfae2 --- /dev/null +++ b/static/css/group_form.css @@ -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; +} \ No newline at end of file diff --git a/templates/base.html b/templates/base.html index fa8e4502..86663664 100644 --- a/templates/base.html +++ b/templates/base.html @@ -38,6 +38,7 @@ <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_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/log.css' %}" type="text/css"> <link rel="stylesheet" href="{% static 'css/login.css' %}" type="text/css"> diff --git a/templates/front/channel_description.html b/templates/front/channel_description.html new file mode 100644 index 00000000..1b6119c7 --- /dev/null +++ b/templates/front/channel_description.html @@ -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 %} diff --git a/templates/front/channels.html b/templates/front/channels.html index 697cc63d..48ef1e47 100644 --- a/templates/front/channels.html +++ b/templates/front/channels.html @@ -32,85 +32,14 @@ </td> <td> <div class="edit-name" data-toggle="modal" data-target="#name-{{ ch.code }}"> - {% if ch.name %} - {{ ch.name }} - {% else %} - <div class="unnamed">unnamed</div> - {% endif %} - <div class="channel-details-mini"> - {% 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 - {% else %} - {{ ch.get_kind_display }} - {% endif %} - </div> + {% 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> </td> <td> diff --git a/templates/integrations/group_form.html b/templates/integrations/group_form.html index ebc763a9..d38e2146 100644 --- a/templates/integrations/group_form.html +++ b/templates/integrations/group_form.html @@ -40,18 +40,40 @@ </div> <div class="form-group {{ form.channels.css_classes }}"> <label for="channels" class="col-sm-2 control-label">Integrations</label> - <div class="col-sm-6"> - {{ form.channels }} + <div id="channel-choices" class="col-sm-6"> + {% 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 %} - <div class="help-block">{{ form.channels.errors|join:"" }}</div> + <div class="help-block"> + {{ form.channels.errors|join:"" }} + </div> {% endif %} </div> </div> <div class="form-group"> <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> </form>